Added auto avatar muting(appearance only) based on avatar complexity (disabled by default). Added several missing debug views.
This commit is contained in:
@@ -2079,6 +2079,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge
|
||||
mFaceMask = 0x0;
|
||||
mDetail = detail;
|
||||
mSculptLevel = -2;
|
||||
mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims
|
||||
mIsMeshAssetLoaded = FALSE;
|
||||
mLODScaleBias.setVec(1,1,1);
|
||||
mHullPoints = NULL;
|
||||
@@ -3152,6 +3153,8 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
|
||||
{
|
||||
F32 area = sculptGetSurfaceArea();
|
||||
|
||||
mSurfaceArea = area;
|
||||
|
||||
const F32 SCULPT_MAX_AREA = 384.f;
|
||||
|
||||
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
|
||||
@@ -4623,18 +4626,83 @@ S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& en
|
||||
genBinormals(i);
|
||||
}
|
||||
|
||||
if (!face.mOctree)
|
||||
{
|
||||
face.createOctree();
|
||||
}
|
||||
|
||||
//LLVector4a* p = (LLVector4a*) face.mPositions;
|
||||
if (isUnique())
|
||||
{ //don't bother with an octree for flexi volumes
|
||||
U32 tri_count = face.mNumIndices/3;
|
||||
|
||||
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
|
||||
intersect.traverse(face.mOctree);
|
||||
if (intersect.mHitFace)
|
||||
for (U32 j = 0; j < tri_count; ++j)
|
||||
{
|
||||
U16 idx0 = face.mIndices[j*3+0];
|
||||
U16 idx1 = face.mIndices[j*3+1];
|
||||
U16 idx2 = face.mIndices[j*3+2];
|
||||
|
||||
const LLVector4a& v0 = face.mPositions[idx0];
|
||||
const LLVector4a& v1 = face.mPositions[idx1];
|
||||
const LLVector4a& v2 = face.mPositions[idx2];
|
||||
|
||||
F32 a,b,t;
|
||||
|
||||
if (LLTriangleRayIntersect(v0, v1, v2,
|
||||
start, dir, a, b, t))
|
||||
{
|
||||
if ((t >= 0.f) && // if hit is after start
|
||||
(t <= 1.f) && // and before end
|
||||
(t < closest_t)) // and this hit is closer
|
||||
{
|
||||
closest_t = t;
|
||||
hit_face = i;
|
||||
|
||||
if (intersection != NULL)
|
||||
{
|
||||
LLVector4a intersect = dir;
|
||||
intersect.mul(closest_t);
|
||||
intersect.add(start);
|
||||
intersection->set(intersect.getF32ptr());
|
||||
}
|
||||
|
||||
|
||||
if (tex_coord != NULL)
|
||||
{
|
||||
LLVector2* tc = (LLVector2*) face.mTexCoords;
|
||||
*tex_coord = ((1.f - a - b) * tc[idx0] +
|
||||
a * tc[idx1] +
|
||||
b * tc[idx2]);
|
||||
|
||||
}
|
||||
|
||||
if (normal!= NULL)
|
||||
{
|
||||
LLVector4* norm = (LLVector4*) face.mNormals;
|
||||
|
||||
*normal = ((1.f - a - b) * LLVector3(norm[idx0]) +
|
||||
a * LLVector3(norm[idx1]) +
|
||||
b * LLVector3(norm[idx2]));
|
||||
}
|
||||
|
||||
if (bi_normal != NULL)
|
||||
{
|
||||
LLVector4* binormal = (LLVector4*) face.mBinormals;
|
||||
*bi_normal = ((1.f - a - b) * LLVector3(binormal[idx0]) +
|
||||
a * LLVector3(binormal[idx1]) +
|
||||
b * LLVector3(binormal[idx2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hit_face = i;
|
||||
if (!face.mOctree)
|
||||
{
|
||||
face.createOctree();
|
||||
}
|
||||
|
||||
LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal);
|
||||
intersect.traverse(face.mOctree);
|
||||
if (intersect.mHitFace)
|
||||
{
|
||||
hit_face = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,6 +971,7 @@ public:
|
||||
S32 getNumFaces() const;
|
||||
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
|
||||
F32 getDetail() const { return mDetail; }
|
||||
F32 getSurfaceArea() const { return mSurfaceArea; }
|
||||
const LLVolumeParams& getParams() const { return mParams; }
|
||||
LLVolumeParams getCopyOfParams() const { return mParams; }
|
||||
const LLProfile& getProfile() const { return *mProfilep; }
|
||||
@@ -1073,6 +1074,7 @@ public:
|
||||
BOOL mUnique;
|
||||
F32 mDetail;
|
||||
S32 mSculptLevel;
|
||||
F32 mSurfaceArea; //unscaled surface area
|
||||
BOOL mIsMeshAssetLoaded;
|
||||
|
||||
LLVolumeParams mParams;
|
||||
|
||||
@@ -371,6 +371,7 @@ set(viewer_SOURCE_FILES
|
||||
llparcelselection.cpp
|
||||
llpatchvertexarray.cpp
|
||||
llphysicsmotion.cpp
|
||||
llphysicsshapebuilderutil.cpp
|
||||
llpolymesh.cpp
|
||||
llpolymorph.cpp
|
||||
llprefschat.cpp
|
||||
@@ -850,6 +851,7 @@ set(viewer_HEADER_FILES
|
||||
llparcelselection.h
|
||||
llpatchvertexarray.h
|
||||
llphysicsmotion.h
|
||||
llphysicsshapebuilderutil.h
|
||||
llpolymesh.h
|
||||
llpolymorph.h
|
||||
llprefschat.h
|
||||
|
||||
@@ -8746,6 +8746,66 @@
|
||||
<key>Value</key>
|
||||
<real>0.0</real>
|
||||
</map>
|
||||
<key>ObjectCostHighThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Threshold at which object cost is considered high (displayed in red).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>50.0</real>
|
||||
</map>
|
||||
<key>ObjectCostLowColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Color for object with a low object cost.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>1.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>ObjectCostMidColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Color for object with a medium object cost.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>1.0</real>
|
||||
<real>0.75</real>
|
||||
<real>0.0</real>
|
||||
<real>0.65</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>ObjectCostHighColor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Color for object a high object cost.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.75</real>
|
||||
</array>
|
||||
</map>
|
||||
|
||||
<key>ParcelMediaAutoPlayEnable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -9583,6 +9643,88 @@
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderAvatarComplexityLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Max visual complexity of avatars in a scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>RenderComplexityColorMin</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Max visual complexity of avatars in a scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>RenderComplexityColorMid</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Max visual complexity of avatars in a scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>RenderComplexityColorMax</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Max visual complexity of avatars in a scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Color4</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
</map>
|
||||
<key>RenderComplexityThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Only color objects higher than render threshold</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>RenderComplexityStaticMax</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Sets a static max value for scaling of RenderComplexity
|
||||
display (-1 for dynamic scaling)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>RenderAvatarLODFactor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -9847,6 +9989,17 @@
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderDebugNormalScale</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Scale of normals in debug display.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.03</real>
|
||||
</map>
|
||||
<key>RenderDebugPipeline</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -11139,6 +11292,28 @@
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteByteLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum bytes of attachments before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderAutoMuteSurfaceAreaLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderUseShaderLOD</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -1081,6 +1081,7 @@ BOOL LLDrawable::isVisible() const
|
||||
LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
|
||||
: LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB)
|
||||
{
|
||||
mBridge = this;
|
||||
mDrawable = root;
|
||||
root->setSpatialBridge(this);
|
||||
|
||||
@@ -1109,6 +1110,15 @@ LLSpatialBridge::~LLSpatialBridge()
|
||||
{
|
||||
group->mSpatialPartition->remove(this, group);
|
||||
}
|
||||
|
||||
//delete octree here so listeners will still be able to access bridge specific state
|
||||
destroyTree();
|
||||
}
|
||||
|
||||
void LLSpatialBridge::destroyTree()
|
||||
{
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
}
|
||||
|
||||
void LLSpatialBridge::updateSpatialExtents()
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LL_LLDRAWPOOLALPHA_H
|
||||
|
||||
#include "lldrawpool.h"
|
||||
#include "llrender.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLFace;
|
||||
@@ -72,6 +73,7 @@ public:
|
||||
virtual void render(S32 pass = 0);
|
||||
/*virtual*/ void prerender();
|
||||
|
||||
void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
|
||||
void renderAlpha(U32 mask);
|
||||
void renderAlphaHighlight(U32 mask);
|
||||
|
||||
|
||||
@@ -1037,51 +1037,48 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
|
||||
llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
|
||||
|
||||
LLViewerTexture* bump = NULL;
|
||||
const F32 BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD = 1000;
|
||||
if( src_image->getMaxVirtualSize() > BRIGHTNESS_DARKNESS_PIXEL_AREA_THRESHOLD )
|
||||
|
||||
bump_image_map_t* entries_list = NULL;
|
||||
void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
|
||||
|
||||
switch( bump_code )
|
||||
{
|
||||
bump_image_map_t* entries_list = NULL;
|
||||
void (*callback_func)( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) = NULL;
|
||||
case BE_BRIGHTNESS:
|
||||
entries_list = &mBrightnessEntries;
|
||||
callback_func = LLBumpImageList::onSourceBrightnessLoaded;
|
||||
break;
|
||||
case BE_DARKNESS:
|
||||
entries_list = &mDarknessEntries;
|
||||
callback_func = LLBumpImageList::onSourceDarknessLoaded;
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch( bump_code )
|
||||
bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
|
||||
if (iter != entries_list->end() && iter->second.notNull())
|
||||
{
|
||||
bump = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
|
||||
raw->clear(0x77, 0x77, 0xFF, 0xFF);
|
||||
|
||||
(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
|
||||
bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
|
||||
}
|
||||
|
||||
if (!src_image->hasCallbacks())
|
||||
{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
|
||||
if (src_image->getWidth() != bump->getWidth() ||
|
||||
src_image->getHeight() != bump->getHeight())// ||
|
||||
//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
|
||||
{
|
||||
case BE_BRIGHTNESS:
|
||||
entries_list = &mBrightnessEntries;
|
||||
callback_func = LLBumpImageList::onSourceBrightnessLoaded;
|
||||
break;
|
||||
case BE_DARKNESS:
|
||||
entries_list = &mDarknessEntries;
|
||||
callback_func = LLBumpImageList::onSourceDarknessLoaded;
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
|
||||
if (iter != entries_list->end() && iter->second.notNull())
|
||||
{
|
||||
bump = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,1);
|
||||
raw->clear(0x77, 0x77, 0xFF, 0xFF);
|
||||
|
||||
(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE);
|
||||
bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
|
||||
}
|
||||
|
||||
if (!src_image->hasCallbacks())
|
||||
{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
|
||||
if (src_image->getWidth() != bump->getWidth() ||
|
||||
src_image->getHeight() != bump->getHeight())// ||
|
||||
//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
|
||||
{
|
||||
src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
|
||||
src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
|
||||
src_image->forceToSaveRawImage(0) ;
|
||||
}
|
||||
src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ;
|
||||
src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL );
|
||||
src_image->forceToSaveRawImage(0) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1593,7 +1590,7 @@ void LLDrawPoolInvisible::endDeferredPass( S32 pass )
|
||||
|
||||
void LLDrawPoolInvisible::renderDeferred( S32 pass )
|
||||
{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff
|
||||
#if 0
|
||||
#if 0
|
||||
LLFastTimer t(FTM_RENDER_INVISIBLE);
|
||||
|
||||
U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
|
||||
|
||||
@@ -89,6 +89,9 @@ const S32 MAX_MESH_VERSION = 999;
|
||||
U32 LLMeshRepository::sBytesReceived = 0;
|
||||
U32 LLMeshRepository::sHTTPRequestCount = 0;
|
||||
U32 LLMeshRepository::sHTTPRetryCount = 0;
|
||||
U32 LLMeshRepository::sLODProcessing = 0;
|
||||
U32 LLMeshRepository::sLODPending = 0;
|
||||
|
||||
U32 LLMeshRepository::sCacheBytesRead = 0;
|
||||
U32 LLMeshRepository::sCacheBytesWritten = 0;
|
||||
U32 LLMeshRepository::sPeakKbps = 0;
|
||||
@@ -206,6 +209,12 @@ public:
|
||||
LLMeshHeaderResponder(const LLVolumeParams& mesh_params)
|
||||
: mMeshParams(mesh_params)
|
||||
{
|
||||
LLMeshRepoThread::sActiveHeaderRequests++;
|
||||
}
|
||||
|
||||
~LLMeshHeaderResponder()
|
||||
{
|
||||
LLMeshRepoThread::sActiveHeaderRequests--;
|
||||
}
|
||||
|
||||
virtual void completedRaw(U32 status, const std::string& reason,
|
||||
@@ -225,6 +234,12 @@ public:
|
||||
LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes)
|
||||
: mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes)
|
||||
{
|
||||
LLMeshRepoThread::sActiveLODRequests++;
|
||||
}
|
||||
|
||||
~LLMeshLODResponder()
|
||||
{
|
||||
LLMeshRepoThread::sActiveLODRequests--;
|
||||
}
|
||||
|
||||
virtual void completedRaw(U32 status, const std::string& reason,
|
||||
@@ -503,6 +518,7 @@ void LLMeshRepoThread::run()
|
||||
mMutex->lock();
|
||||
LODRequest req = mLODReqQ.front();
|
||||
mLODReqQ.pop();
|
||||
LLMeshRepository::sLODProcessing--;
|
||||
mMutex->unlock();
|
||||
if (fetchMeshLOD(req.mMeshParams, req.mLOD))
|
||||
{
|
||||
@@ -611,6 +627,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
{
|
||||
LLMutexLock lock(mMutex);
|
||||
mLODReqQ.push(req);
|
||||
LLMeshRepository::sLODProcessing++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -713,7 +730,6 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
++sActiveLODRequests;
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
|
||||
new LLMeshSkinInfoResponder(mesh_id, offset, size));
|
||||
@@ -786,7 +802,6 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
++sActiveLODRequests;
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshDecompositionResponder(mesh_id, offset, size));
|
||||
@@ -859,7 +874,6 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
++sActiveLODRequests;
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
|
||||
@@ -910,7 +924,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
|
||||
std::string http_url = constructUrl(mesh_params.getSculptID());
|
||||
if (!http_url.empty())
|
||||
{
|
||||
++sActiveHeaderRequests;
|
||||
retval = true;
|
||||
//grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
|
||||
//within the first 4KB
|
||||
@@ -976,7 +989,6 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
++sActiveLODRequests;
|
||||
retval = true;
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
|
||||
@@ -1052,6 +1064,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
|
||||
{
|
||||
LODRequest req(mesh_params, iter->second[i]);
|
||||
mLODReqQ.push(req);
|
||||
LLMeshRepository::sLODProcessing++;
|
||||
}
|
||||
}
|
||||
mPendingLOD.erase(iter);
|
||||
@@ -1725,7 +1738,6 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
|
||||
const LLIOPipe::buffer_ptr_t& buffer)
|
||||
{
|
||||
|
||||
LLMeshRepoThread::sActiveLODRequests--;
|
||||
S32 data_size = buffer->countAfter(channels.in(), NULL);
|
||||
|
||||
if (status < 200 || status > 400)
|
||||
@@ -1942,7 +1954,6 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
|
||||
const LLChannelDescriptors& channels,
|
||||
const LLIOPipe::buffer_ptr_t& buffer)
|
||||
{
|
||||
LLMeshRepoThread::sActiveHeaderRequests--;
|
||||
if (status < 200 || status > 400)
|
||||
{
|
||||
//llwarns
|
||||
@@ -2385,6 +2396,7 @@ void LLMeshRepository::notifyLoadedMeshes()
|
||||
LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
|
||||
mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
|
||||
mPendingRequests.erase(mPendingRequests.begin());
|
||||
LLMeshRepository::sLODPending--;
|
||||
push_count--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,15 +464,14 @@ private:
|
||||
|
||||
class LLMeshRepository
|
||||
{
|
||||
private:
|
||||
S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
|
||||
|
||||
public:
|
||||
|
||||
//metrics
|
||||
static U32 sBytesReceived;
|
||||
static U32 sHTTPRequestCount;
|
||||
static U32 sHTTPRetryCount;
|
||||
static U32 sLODPending;
|
||||
static U32 sLODProcessing;
|
||||
static U32 sCacheBytesRead;
|
||||
static U32 sCacheBytesWritten;
|
||||
static U32 sPeakKbps;
|
||||
|
||||
@@ -1078,6 +1078,8 @@ void LLSpatialGroup::clearOcclusionState(eOcclusionState state, S32 mode)
|
||||
|
||||
LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
|
||||
mState(0),
|
||||
mGeometryBytes(0),
|
||||
mSurfaceArea(0.f),
|
||||
mBuilt(0.f),
|
||||
mOctreeNode(node),
|
||||
mSpatialPartition(part),
|
||||
@@ -1086,9 +1088,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
|
||||
mDistance(0.f),
|
||||
mDepth(0.f),
|
||||
mLastUpdateDistance(-1.f),
|
||||
mLastUpdateTime(gFrameTimeSeconds),
|
||||
mViewAngle(0.f),
|
||||
mLastUpdateViewAngle(-1.f)
|
||||
mLastUpdateTime(gFrameTimeSeconds)
|
||||
{
|
||||
sNodeCount++;
|
||||
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
|
||||
@@ -1302,6 +1302,17 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
|
||||
}
|
||||
}
|
||||
|
||||
//clean up avatar attachment stats
|
||||
LLSpatialBridge* bridge = mSpatialPartition->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.notNull())
|
||||
{
|
||||
bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes;
|
||||
bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea;
|
||||
}
|
||||
}
|
||||
|
||||
clearDrawMap();
|
||||
mVertexBuffer = NULL;
|
||||
mBufferMap.clear();
|
||||
@@ -1659,7 +1670,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
|
||||
//==============================================
|
||||
|
||||
LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
|
||||
: mRenderByGroup(render_by_group)
|
||||
: mRenderByGroup(render_by_group), mBridge(NULL)
|
||||
{
|
||||
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
|
||||
mOcclusionEnabled = TRUE;
|
||||
@@ -2718,6 +2729,115 @@ void renderUpdateType(LLDrawable* drawablep)
|
||||
}
|
||||
}
|
||||
|
||||
void renderComplexityDisplay(LLDrawable* drawablep)
|
||||
{
|
||||
LLViewerObject* vobj = drawablep->getVObj();
|
||||
if (!vobj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLVOVolume *voVol = dynamic_cast<LLVOVolume*>(vobj);
|
||||
|
||||
if (!voVol)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!voVol->isRoot())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
F32 cost = (F32) voVol->getRenderCost(textures);
|
||||
|
||||
// add any child volumes
|
||||
LLViewerObject::const_child_list_t children = voVol->getChildren();
|
||||
for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
|
||||
{
|
||||
const LLViewerObject *child = *iter;
|
||||
const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child);
|
||||
if (child_volume)
|
||||
{
|
||||
cost += child_volume->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
// add texture cost
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
|
||||
F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax();
|
||||
|
||||
|
||||
|
||||
// allow user to set a static color scale
|
||||
if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0)
|
||||
{
|
||||
cost_max = gSavedSettings.getS32("RenderComplexityStaticMax");
|
||||
}
|
||||
|
||||
F32 cost_ratio = cost / cost_max;
|
||||
|
||||
// cap cost ratio at 1.0f in case cost_max is at a low threshold
|
||||
cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio;
|
||||
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
|
||||
LLColor4 color;
|
||||
const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin");
|
||||
const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid");
|
||||
const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax");
|
||||
|
||||
if (cost_ratio < 0.5f)
|
||||
{
|
||||
color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2);
|
||||
}
|
||||
|
||||
LLSD color_val = color.getValue();
|
||||
|
||||
// don't highlight objects below the threshold
|
||||
if (cost > gSavedSettings.getS32("RenderComplexityThreshold"))
|
||||
{
|
||||
glColor4f(color[0],color[1],color[2],0.5f);
|
||||
|
||||
|
||||
S32 num_faces = drawablep->getNumFaces();
|
||||
if (num_faces)
|
||||
{
|
||||
for (S32 i = 0; i < num_faces; ++i)
|
||||
{
|
||||
pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
}
|
||||
LLViewerObject::const_child_list_t children = voVol->getChildren();
|
||||
for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
|
||||
{
|
||||
const LLViewerObject *child = *iter;
|
||||
if (child)
|
||||
{
|
||||
num_faces = child->getNumFaces();
|
||||
if (num_faces)
|
||||
{
|
||||
for (S32 i = 0; i < num_faces; ++i)
|
||||
{
|
||||
pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
voVol->setDebugText(llformat("%4.0f", cost));
|
||||
}
|
||||
|
||||
void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
|
||||
{
|
||||
@@ -2811,7 +2931,490 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
|
||||
{
|
||||
drawBoxOutline(pos,size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void renderNormals(LLDrawable* drawablep)
|
||||
{
|
||||
LLVertexBuffer::unbind();
|
||||
|
||||
LLVOVolume* vol = drawablep->getVOVolume();
|
||||
if (vol)
|
||||
{
|
||||
LLVolume* volume = vol->getVolume();
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix((F32*) vol->getRelativeXform().mMatrix);
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
LLVector4a scale(gSavedSettings.getF32("RenderDebugNormalScale"));
|
||||
|
||||
for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
|
||||
{
|
||||
const LLVolumeFace& face = volume->getVolumeFace(i);
|
||||
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
gGL.begin(LLRender::LINES);
|
||||
LLVector4a n,p;
|
||||
|
||||
n.setMul(face.mNormals[j], scale);
|
||||
p.setAdd(face.mPositions[j], n);
|
||||
|
||||
gGL.diffuseColor4f(1,1,1,1);
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
|
||||
if (face.mBinormals)
|
||||
{
|
||||
n.setMul(face.mBinormals[j], scale);
|
||||
p.setAdd(face.mPositions[j], n);
|
||||
|
||||
gGL.diffuseColor4f(0,1,1,1);
|
||||
gGL.vertex3fv(face.mPositions[j].getF32ptr());
|
||||
gGL.vertex3fv(p.getF32ptr());
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale)
|
||||
{
|
||||
const S32 DEFAULT_DETAIL = 1;
|
||||
const F32 LARGE_THRESHOLD = 5.f;
|
||||
const F32 MEGA_THRESHOLD = 25.f;
|
||||
|
||||
S32 detail = DEFAULT_DETAIL;
|
||||
F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f;
|
||||
|
||||
if (avg_scale > LARGE_THRESHOLD)
|
||||
{
|
||||
detail += 1;
|
||||
if (avg_scale > MEGA_THRESHOLD)
|
||||
{
|
||||
detail += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return detail;
|
||||
}
|
||||
|
||||
void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color)
|
||||
{
|
||||
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
|
||||
LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
|
||||
const LLVector3 center(0,0,0);
|
||||
const LLVector3 size(0.25f,0.25f,0.25f);
|
||||
|
||||
if (decomp)
|
||||
{
|
||||
if (!decomp->mBaseHullMesh.empty())
|
||||
{
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals);
|
||||
}
|
||||
else
|
||||
{
|
||||
gMeshRepo.buildPhysicsMesh(*decomp);
|
||||
gGL.diffuseColor4f(0,1,1,1);
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.diffuseColor3f(1,0,1);
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
}
|
||||
|
||||
void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color)
|
||||
{
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals);
|
||||
LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glPolygonOffset(3.f, 3.f);
|
||||
glLineWidth(3.f);
|
||||
gGL.diffuseColor4fv(line_color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals);
|
||||
glLineWidth(1.f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume)
|
||||
{
|
||||
U8 physics_type = volume->getPhysicsShapeType();
|
||||
|
||||
if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//not allowed to return at this point without rendering *something*
|
||||
|
||||
F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold");
|
||||
F32 cost = volume->getObjectCost();
|
||||
|
||||
LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor");
|
||||
LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor");
|
||||
LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor");
|
||||
|
||||
F32 normalizedCost = 1.f - exp( -(cost / threshold) );
|
||||
|
||||
LLColor4 color;
|
||||
if ( normalizedCost <= 0.5f )
|
||||
{
|
||||
color = lerp( low, mid, 2.f * normalizedCost );
|
||||
}
|
||||
else
|
||||
{
|
||||
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();
|
||||
|
||||
LLPhysicsVolumeParams physics_params(volume_params,
|
||||
physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
|
||||
|
||||
LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec;
|
||||
LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec);
|
||||
|
||||
U32 type = physics_spec.getType();
|
||||
|
||||
LLVector3 center(0,0,0);
|
||||
LLVector3 size(0.25f,0.25f,0.25f);
|
||||
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix);
|
||||
|
||||
if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH)
|
||||
{
|
||||
//Skip. no
|
||||
LLUUID mesh_id = volume->getVolume()->getParams().getSculptID();
|
||||
LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id);
|
||||
|
||||
if (decomp)
|
||||
{ //render a physics based mesh
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
if (!decomp->mHull.empty())
|
||||
{ //decomposition exists, use that
|
||||
|
||||
if (decomp->mMesh.empty())
|
||||
{
|
||||
gMeshRepo.buildPhysicsMesh(*decomp);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < decomp->mMesh.size(); ++i)
|
||||
{
|
||||
render_hull(decomp->mMesh[i], color, line_color);
|
||||
}
|
||||
}
|
||||
else if (!decomp->mPhysicsShapeMesh.empty())
|
||||
{
|
||||
//decomp has physics mesh, render that mesh
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
gGL.diffuseColor4fv(line_color.mV);
|
||||
LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals);
|
||||
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.empty())
|
||||
{
|
||||
//attempt to fetch physics shape mesh if available
|
||||
gMeshRepo.fetchPhysicsShape(mesh_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.diffuseColor3f(1,1,0);
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX ||
|
||||
type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX)
|
||||
{
|
||||
if (volume->isMesh())
|
||||
{
|
||||
renderMeshBaseHull(volume, data_mask, color, line_color);
|
||||
}
|
||||
/*else
|
||||
{
|
||||
LLVolumeParams volume_params = volume->getVolume()->getParams();
|
||||
S32 detail = get_physics_detail(volume_params, volume->getScale());
|
||||
LLVolume* phys_volume = LLPrimitive::getVolumeManager()->refVolume(volume_params, detail);
|
||||
|
||||
if (!phys_volume->mHullPoints)
|
||||
{ //build convex hull
|
||||
std::vector<LLVector3> pos;
|
||||
std::vector<U16> index;
|
||||
|
||||
S32 index_offset = 0;
|
||||
|
||||
for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i)
|
||||
{
|
||||
const LLVolumeFace& face = phys_volume->getVolumeFace(i);
|
||||
if (index_offset + face.mNumVertices > 65535)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < face.mNumVertices; ++j)
|
||||
{
|
||||
pos.push_back(LLVector3(face.mPositions[j].getF32ptr()));
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < face.mNumIndices; ++j)
|
||||
{
|
||||
index.push_back(face.mIndices[j]+index_offset);
|
||||
}
|
||||
|
||||
index_offset += face.mNumVertices;
|
||||
}
|
||||
|
||||
if (!pos.empty() && !index.empty())
|
||||
{
|
||||
LLCDMeshData mesh;
|
||||
mesh.mIndexBase = &index[0];
|
||||
mesh.mVertexBase = pos[0].mV;
|
||||
mesh.mNumVertices = pos.size();
|
||||
mesh.mVertexStrideBytes = 12;
|
||||
mesh.mIndexStrideBytes = 6;
|
||||
mesh.mIndexType = LLCDMeshData::INT_16;
|
||||
|
||||
mesh.mNumTriangles = index.size()/3;
|
||||
|
||||
LLCDMeshData res;
|
||||
|
||||
LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res );
|
||||
|
||||
//copy res into phys_volume
|
||||
phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices);
|
||||
phys_volume->mNumHullPoints = res.mNumVertices;
|
||||
|
||||
S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF;
|
||||
phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size);
|
||||
phys_volume->mNumHullIndices = res.mNumTriangles*3;
|
||||
|
||||
const F32* v = res.mVertexBase;
|
||||
|
||||
for (S32 i = 0; i < res.mNumVertices; ++i)
|
||||
{
|
||||
F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes);
|
||||
phys_volume->mHullPoints[i].load3(p);
|
||||
}
|
||||
|
||||
if (res.mIndexType == LLCDMeshData::INT_16)
|
||||
{
|
||||
for (S32 i = 0; i < res.mNumTriangles; ++i)
|
||||
{
|
||||
U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes);
|
||||
|
||||
phys_volume->mHullIndices[i*3+0] = idx[0];
|
||||
phys_volume->mHullIndices[i*3+1] = idx[1];
|
||||
phys_volume->mHullIndices[i*3+2] = idx[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (S32 i = 0; i < res.mNumTriangles; ++i)
|
||||
{
|
||||
U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes);
|
||||
|
||||
phys_volume->mHullIndices[i*3+0] = (U16) idx[0];
|
||||
phys_volume->mHullIndices[i*3+1] = (U16) idx[1];
|
||||
phys_volume->mHullIndices[i*3+2] = (U16) idx[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (phys_volume->mHullPoints)
|
||||
{
|
||||
//render hull
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
gGL.diffuseColor4fv(line_color.mV);
|
||||
LLVertexBuffer::unbind();
|
||||
|
||||
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0);
|
||||
|
||||
LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.diffuseColor4f(1,0,1,1);
|
||||
drawBoxOutline(center, size);
|
||||
}
|
||||
|
||||
LLPrimitive::sVolumeManager->unrefVolume(phys_volume);
|
||||
}*/
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX)
|
||||
{
|
||||
LLVector3 center = physics_spec.getCenter();
|
||||
LLVector3 scale = physics_spec.getScale();
|
||||
LLVector3 vscale = volume->getScale()*2.f;
|
||||
scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
drawBox(center, scale);
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE)
|
||||
{
|
||||
/*LLVolumeParams volume_params;
|
||||
volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
|
||||
volume_params.setBeginAndEndS( 0.f, 1.f );
|
||||
volume_params.setBeginAndEndT( 0.f, 1.f );
|
||||
volume_params.setRatio ( 1, 1 );
|
||||
volume_params.setShear ( 0, 0 );
|
||||
LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
pushVerts(sphere);
|
||||
LLPrimitive::sVolumeManager->unrefVolume(sphere);*/
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER)
|
||||
{
|
||||
LLVolumeParams volume_params;
|
||||
volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
|
||||
volume_params.setBeginAndEndS( 0.f, 1.f );
|
||||
volume_params.setBeginAndEndT( 0.f, 1.f );
|
||||
volume_params.setRatio ( 1, 1 );
|
||||
volume_params.setShear ( 0, 0 );
|
||||
LLVolume* cylinder = LLPrimitive::getVolumeManager()->refVolume(volume_params, 3);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
pushVerts(cylinder);
|
||||
LLPrimitive::getVolumeManager()->unrefVolume(cylinder);
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH)
|
||||
{
|
||||
LLVolumeParams volume_params = volume->getVolume()->getParams();
|
||||
S32 detail = get_physics_detail(volume_params, volume->getScale());
|
||||
|
||||
LLVolume* phys_volume = LLPrimitive::getVolumeManager()->refVolume(volume_params, detail);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
gGL.diffuseColor4fv(line_color.mV);
|
||||
pushVerts(phys_volume);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
pushVerts(phys_volume);
|
||||
LLPrimitive::getVolumeManager()->unrefVolume(phys_volume);
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX)
|
||||
{
|
||||
LLVolumeParams volume_params = volume->getVolume()->getParams();
|
||||
S32 detail = get_physics_detail(volume_params, volume->getScale());
|
||||
|
||||
LLVolume* phys_volume = LLPrimitive::getVolumeManager()->refVolume(volume_params, detail);
|
||||
|
||||
if (phys_volume->mHullPoints && phys_volume->mHullIndices)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0);
|
||||
LLVertexBuffer::unbind();
|
||||
glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints);
|
||||
gGL.diffuseColor4fv(line_color.mV);
|
||||
gGL.syncMatrices();
|
||||
glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
|
||||
|
||||
gGL.diffuseColor4fv(color.mV);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.diffuseColor3f(1,0,1);
|
||||
drawBoxOutline(center, size);
|
||||
gMeshRepo.buildHull(volume_params, detail);
|
||||
}
|
||||
LLPrimitive::getVolumeManager()->unrefVolume(phys_volume);
|
||||
}
|
||||
else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT)
|
||||
{
|
||||
//TODO: implement sculpted prim physics display
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "Unhandled type" << llendl;
|
||||
}
|
||||
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
||||
void renderPhysicsShapes(LLSpatialGroup* group)
|
||||
{
|
||||
for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
|
||||
{
|
||||
LLDrawable* drawable = *i;
|
||||
LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE )
|
||||
{
|
||||
if (!group->mSpatialPartition->isBridge())
|
||||
{
|
||||
gGL.pushMatrix();
|
||||
LLVector3 trans = drawable->getRegion()->getOriginAgent();
|
||||
gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
|
||||
renderPhysicsShape(drawable, volume);
|
||||
gGL.popMatrix();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderPhysicsShape(drawable, volume);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerObject* object = drawable->getVObj();
|
||||
if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH)
|
||||
{
|
||||
//push face vertices for terrain
|
||||
for (S32 i = 0; i < drawable->getNumFaces(); ++i)
|
||||
{
|
||||
LLFace* face = drawable->getFace(i);
|
||||
LLVertexBuffer* buff = face->getVertexBuffer();
|
||||
if (buff)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
|
||||
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||
gGL.diffuseColor3f(0.2f, 0.5f, 0.3f);
|
||||
buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
|
||||
|
||||
gGL.diffuseColor3f(0.2f, 1.f, 0.3f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderTexturePriority(LLDrawable* drawable)
|
||||
@@ -2908,6 +3511,43 @@ void renderBatchSize(LLDrawInfo* params)
|
||||
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
|
||||
void renderShadowFrusta(LLDrawInfo* params)
|
||||
{
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
gGL.setSceneBlendType(LLRender::BT_ADD);
|
||||
|
||||
LLVector4a center;
|
||||
center.setAdd(params->mExtents[1], params->mExtents[0]);
|
||||
center.mul(0.5f);
|
||||
LLVector4a size;
|
||||
size.setSub(params->mExtents[1],params->mExtents[0]);
|
||||
size.mul(0.5f);
|
||||
|
||||
if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size))
|
||||
{
|
||||
gGL.diffuseColor3f(1,0,0);
|
||||
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size))
|
||||
{
|
||||
gGL.diffuseColor3f(0,1,0);
|
||||
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size))
|
||||
{
|
||||
gGL.diffuseColor3f(0,0,1);
|
||||
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size))
|
||||
{
|
||||
gGL.diffuseColor3f(1,0,1);
|
||||
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
|
||||
}
|
||||
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
|
||||
|
||||
void renderLights(LLDrawable* drawablep)
|
||||
{
|
||||
if (!drawablep->isLight())
|
||||
@@ -3248,11 +3888,16 @@ public:
|
||||
for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
|
||||
{
|
||||
LLDrawable* drawable = *i;
|
||||
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
|
||||
{
|
||||
renderBoundingBox(drawable);
|
||||
}
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS))
|
||||
{
|
||||
renderNormals(drawable);
|
||||
}
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
|
||||
{
|
||||
@@ -3293,6 +3938,10 @@ public:
|
||||
{
|
||||
renderUpdateType(drawable);
|
||||
}
|
||||
if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
|
||||
{
|
||||
renderComplexityDisplay(drawable);
|
||||
}
|
||||
|
||||
LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
|
||||
|
||||
@@ -3344,11 +3993,50 @@ public:
|
||||
{
|
||||
renderBatchSize(draw_info);
|
||||
}
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
|
||||
{
|
||||
renderShadowFrusta(draw_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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:
|
||||
@@ -3467,6 +4155,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 |
|
||||
@@ -3475,13 +4182,16 @@ void LLSpatialPartition::renderDebug()
|
||||
LLPipeline::RENDER_DEBUG_BATCH_SIZE |
|
||||
LLPipeline::RENDER_DEBUG_UPDATE_TYPE |
|
||||
LLPipeline::RENDER_DEBUG_BBOXES |
|
||||
LLPipeline::RENDER_DEBUG_NORMALS |
|
||||
LLPipeline::RENDER_DEBUG_POINTS |
|
||||
LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
|
||||
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
|
||||
LLPipeline::RENDER_DEBUG_RAYCAST |
|
||||
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
|
||||
LLPipeline::RENDER_DEBUG_AGENT_TARGET |
|
||||
LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
|
||||
//LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
|
||||
LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA |
|
||||
LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -376,6 +376,9 @@ public:
|
||||
bridge_list_t mBridgeList;
|
||||
buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture
|
||||
|
||||
U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node
|
||||
F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
|
||||
|
||||
F32 mBuilt;
|
||||
OctreeNode* mOctreeNode;
|
||||
LLSpatialPartition* mSpatialPartition;
|
||||
@@ -455,9 +458,10 @@ public:
|
||||
BOOL isVisible(const LLVector3& v);
|
||||
bool isHUDPartition() ;
|
||||
|
||||
virtual LLSpatialBridge* asBridge() { return NULL; }
|
||||
virtual BOOL isBridge() { return asBridge() != NULL; }
|
||||
LLSpatialBridge* asBridge() { return mBridge; }
|
||||
BOOL isBridge() { return asBridge() != NULL; }
|
||||
|
||||
void renderPhysicsShapes();
|
||||
void renderDebug();
|
||||
void renderIntersectingBBoxes(LLCamera* camera);
|
||||
void restoreGL();
|
||||
@@ -467,6 +471,9 @@ public:
|
||||
|
||||
public:
|
||||
LLSpatialGroup::OctreeNode* mOctree;
|
||||
LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this
|
||||
// use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe
|
||||
// to call asBridge() from the destructor
|
||||
BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed
|
||||
BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane
|
||||
U32 mBufferUsage;
|
||||
@@ -491,8 +498,9 @@ public:
|
||||
|
||||
LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
|
||||
|
||||
virtual BOOL isSpatialBridge() const { return TRUE; }
|
||||
void destroyTree();
|
||||
|
||||
virtual BOOL isSpatialBridge() const { return TRUE; }
|
||||
virtual void updateSpatialExtents();
|
||||
virtual void updateBinRadius();
|
||||
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
|
||||
@@ -503,11 +511,11 @@ public:
|
||||
virtual void shiftPos(const LLVector4a& vec);
|
||||
virtual void cleanupReferences();
|
||||
virtual LLSpatialPartition* asPartition() { return this; }
|
||||
virtual LLSpatialBridge* asBridge() { return this; }
|
||||
|
||||
|
||||
virtual LLCamera transformCamera(LLCamera& camera);
|
||||
|
||||
LLDrawable* mDrawable;
|
||||
LLPointer<LLVOAvatar> mAvatar;
|
||||
};
|
||||
|
||||
class LLCullResult
|
||||
|
||||
@@ -764,6 +764,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
|
||||
{
|
||||
LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
|
||||
gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
|
||||
gPipeline.renderPhysicsDisplay();
|
||||
}
|
||||
|
||||
LLGLState::checkStates();
|
||||
|
||||
@@ -1489,6 +1489,21 @@ void init_debug_rendering_menu(LLMenuGL* menu)
|
||||
sub_menu->append(new LLMenuItemCheckGL("Update Types", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_UPDATE_TYPE));
|
||||
sub_menu->append(new LLMenuItemCheckGL("Physics Shapes", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES));
|
||||
sub_menu->append(new LLMenuItemCheckGL("Normals", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_NORMALS));
|
||||
sub_menu->append(new LLMenuItemCheckGL("LOD Info", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_LOD_INFO));
|
||||
sub_menu->append(new LLMenuItemCheckGL("Wind Vectors", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_WIND_VECTORS));
|
||||
sub_menu->append(new LLMenuItemCheckGL("Complexity", &LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)); ;
|
||||
|
||||
sub_menu = new LLMenuGL("Render Tests");
|
||||
|
||||
@@ -1632,6 +1647,10 @@ void init_debug_avatar_menu(LLMenuGL* menu)
|
||||
&LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_AGENT_TARGET));
|
||||
menu->append(new LLMenuItemCheckGL("Attachment Bytes",
|
||||
&LLPipeline::toggleRenderDebug, NULL,
|
||||
&LLPipeline::toggleRenderDebugControl,
|
||||
(void*)LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES));
|
||||
menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation));
|
||||
menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments));
|
||||
menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL ));
|
||||
|
||||
@@ -689,6 +689,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
LLViewerObject(id, pcode, regionp),
|
||||
mIsDummy(FALSE),
|
||||
mSpecialRenderMode(0),
|
||||
mAttachmentGeometryBytes(0),
|
||||
mAttachmentSurfaceArea(0.f),
|
||||
mTurning(FALSE),
|
||||
mPelvisToFoot(0.f),
|
||||
mLastSkeletonSerialNum( 0 ),
|
||||
@@ -1370,6 +1372,7 @@ void LLVOAvatar::initInstance(void)
|
||||
mesh->setName(mesh_name);
|
||||
mesh->setMeshID(mesh_index);
|
||||
mesh->setPickName(mesh_dict->mPickName);
|
||||
mesh->setIsTransparent(FALSE);
|
||||
switch((int)mesh_index)
|
||||
{
|
||||
case MESH_ID_HAIR:
|
||||
@@ -4044,6 +4047,16 @@ void LLVOAvatar::slamPosition()
|
||||
mRoot.updateWorldMatrixChildren();
|
||||
}
|
||||
|
||||
bool LLVOAvatar::isVisuallyMuted()
|
||||
{
|
||||
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
|
||||
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
|
||||
|
||||
return LLMuteList::getInstance()->isMuted(getID()) ||
|
||||
(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
|
||||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// updateCharacter()
|
||||
// called on both your avatar and other avatars
|
||||
@@ -4119,8 +4132,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
size.setSub(ext[1],ext[0]);
|
||||
F32 mag = size.getLength3().getF32()*0.5f;
|
||||
|
||||
|
||||
F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
|
||||
if (LLMuteList::getInstance()->isMuted(getID()))
|
||||
if (isVisuallyMuted())
|
||||
{ // muted avatars update at 16 hz
|
||||
mUpdatePeriod = 16;
|
||||
}
|
||||
@@ -5234,6 +5248,7 @@ void LLVOAvatar::updateTextures()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
|
||||
@@ -10426,19 +10441,41 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
|
||||
|
||||
void LLVOAvatar::idleUpdateRenderCost()
|
||||
{
|
||||
static const U32 ARC_BODY_PART_COST = 200;
|
||||
static const U32 ARC_LIMIT = 20000;
|
||||
|
||||
static std::set<LLUUID> all_textures;
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))
|
||||
{ //set debug text to attachment geometry bytes here so render cost will override
|
||||
setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
|
||||
}
|
||||
|
||||
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
U32 shame = 1;
|
||||
U32 cost = 0;
|
||||
LLVOVolume::texture_cost_t textures;
|
||||
|
||||
std::set<LLUUID> textures;
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
{
|
||||
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
|
||||
ETextureIndex tex_index = baked_dict->mTextureIndex;
|
||||
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
|
||||
{
|
||||
if (isTextureVisible(tex_index))
|
||||
{
|
||||
cost +=ARC_BODY_PART_COST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attachment_map_t::const_iterator iter;
|
||||
for (iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
|
||||
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
|
||||
iter != mAttachmentPoints.end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerJointAttachment* attachment = iter->second;
|
||||
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
|
||||
@@ -10448,52 +10485,89 @@ void LLVOAvatar::idleUpdateRenderCost()
|
||||
const LLViewerObject* attached_object = (*attachment_iter);
|
||||
if (attached_object && !attached_object->isHUDAttachment())
|
||||
{
|
||||
textures.clear();
|
||||
const LLDrawable* drawable = attached_object->mDrawable;
|
||||
if (drawable)
|
||||
{
|
||||
shame += 10;
|
||||
LLVOVolume* volume = drawable->getVOVolume();
|
||||
const LLVOVolume* volume = drawable->getVOVolume();
|
||||
if (volume)
|
||||
{
|
||||
shame += calc_shame(volume, textures);
|
||||
cost += volume->getRenderCost(textures);
|
||||
|
||||
const_child_list_t children = volume->getChildren();
|
||||
for (const_child_list_t::const_iterator child_iter = children.begin();
|
||||
child_iter != children.end();
|
||||
++child_iter)
|
||||
{
|
||||
LLViewerObject* child_obj = *child_iter;
|
||||
LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
|
||||
if (child)
|
||||
{
|
||||
cost += child->getRenderCost(textures);
|
||||
}
|
||||
}
|
||||
|
||||
for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
|
||||
{
|
||||
// add the cost of each individual texture in the linkset
|
||||
cost += iter->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sDoProperArc)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Diagnostic output to identify all avatar-related textures.
|
||||
// Does not affect rendering cost calculation.
|
||||
// Could be wrapped in a debug option if output becomes problematic.
|
||||
if (isSelf())
|
||||
{
|
||||
std::set<LLUUID>::const_iterator tex_iter;
|
||||
for(tex_iter = textures.begin();tex_iter != textures.end();++tex_iter)
|
||||
// print any attachment textures we didn't already know about.
|
||||
for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)
|
||||
{
|
||||
LLViewerTexture* img = LLViewerTextureManager::getFetchedTexture(*tex_iter);
|
||||
if(img)
|
||||
LLUUID image_id = it->first;
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
shame += (img->getHeight() * img->getWidth()) >> 4;
|
||||
// attachment texture not previously seen.
|
||||
llinfos << "attachment_texture: " << image_id.asString() << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
|
||||
// print any avatar textures we didn't already know about
|
||||
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
|
||||
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
|
||||
++iter)
|
||||
{
|
||||
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
|
||||
// TODO: MULTI-WEARABLE: handle multiple textures for self
|
||||
const LLViewerTexture* te_image = getTEImage(iter->first);//getImage(iter->first,0);
|
||||
if (!te_image)
|
||||
continue;
|
||||
LLUUID image_id = te_image->getID();
|
||||
if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
|
||||
continue;
|
||||
if (all_textures.find(image_id) == all_textures.end())
|
||||
{
|
||||
llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
|
||||
all_textures.insert(image_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
shame += textures.size() * 5;
|
||||
|
||||
setDebugText(llformat("%d", shame));
|
||||
F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
|
||||
F32 red = llmin((F32) shame/1024.f, 1.f);
|
||||
if(sDoProperArc)
|
||||
{
|
||||
green = 1.f-llclamp(((F32)shame-1000000.f)/1000000.f, 0.f, 1.f);
|
||||
red = llmin((F32)shame/1000000.f, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
green = 1.f-llclamp(((F32)shame-1024.f)/1024.f, 0.f, 1.f);
|
||||
red = llmin((F32)shame/1024.f, 1.f);
|
||||
}
|
||||
setDebugText(llformat("%d", cost));
|
||||
mVisualComplexity = cost;
|
||||
F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
|
||||
F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
|
||||
mText->setColor(LLColor4(red,green,0,1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// static
|
||||
BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index)
|
||||
{
|
||||
|
||||
@@ -287,6 +287,7 @@ private:
|
||||
BOOL mPreviousFullyLoaded;
|
||||
BOOL mFullyLoadedInitialized;
|
||||
S32 mFullyLoadedFrameCounter;
|
||||
S32 mVisualComplexity;
|
||||
LLFrameTimer mFullyLoadedTimer;
|
||||
LLFrameTimer mRuthTimer;
|
||||
|
||||
@@ -379,6 +380,8 @@ public:
|
||||
// Graphical stuff for objects - maybe broken out into render class later?
|
||||
U32 renderFootShadows();
|
||||
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
|
||||
bool isVisuallyMuted();
|
||||
|
||||
U32 renderRigid();
|
||||
U32 renderSkinned(EAvatarRenderPass pass);
|
||||
F32 getLastSkinTime() { return mLastSkinTime; }
|
||||
@@ -390,6 +393,9 @@ public:
|
||||
static void restoreGL();
|
||||
BOOL mIsDummy; // for special views
|
||||
S32 mSpecialRenderMode; // special lighting
|
||||
U32 mAttachmentGeometryBytes; //number of bytes in attached geometry
|
||||
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
|
||||
|
||||
private:
|
||||
bool shouldAlphaMask();
|
||||
|
||||
|
||||
@@ -1032,6 +1032,14 @@ BOOL LLVOVolume::calcLOD()
|
||||
cur_detail = computeLODDetail(llround(distance, 0.01f),
|
||||
llround(radius, 0.01f));
|
||||
|
||||
|
||||
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO))
|
||||
{
|
||||
//setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
|
||||
|
||||
setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
|
||||
}
|
||||
|
||||
if (cur_detail != mLOD)
|
||||
{
|
||||
mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
|
||||
@@ -3346,6 +3354,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
LLFastTimer ftm2(FTM_REBUILD_VOLUME_VB);
|
||||
|
||||
LLVOAvatar* pAvatarVO = NULL;
|
||||
|
||||
LLSpatialBridge* bridge = group->mSpatialPartition->asBridge();
|
||||
if (bridge)
|
||||
{
|
||||
if (bridge->mAvatar.isNull())
|
||||
{
|
||||
LLViewerObject* vobj = bridge->mDrawable->getVObj();
|
||||
if (vobj)
|
||||
{
|
||||
bridge->mAvatar = vobj->getAvatar();
|
||||
}
|
||||
}
|
||||
|
||||
pAvatarVO = bridge->mAvatar;
|
||||
}
|
||||
|
||||
if (pAvatarVO)
|
||||
{
|
||||
pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes;
|
||||
pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea;
|
||||
}
|
||||
|
||||
group->mGeometryBytes = 0;
|
||||
group->mSurfaceArea = 0;
|
||||
|
||||
group->clearDrawMap();
|
||||
|
||||
mFaceList.clear();
|
||||
@@ -3384,12 +3418,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
LLVOVolume* vobj = drawablep->getVOVolume();
|
||||
|
||||
if (!vobj)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vobj->isMesh() &&
|
||||
(vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLVolume* volume = vobj->getVolume();
|
||||
if (volume)
|
||||
{
|
||||
const LLVector3& scale = vobj->getScale();
|
||||
group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]);
|
||||
}
|
||||
|
||||
llassert_always(vobj);
|
||||
vobj->updateTextureVirtualSize(true);
|
||||
vobj->preRebuild();
|
||||
@@ -3434,7 +3480,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
//Determine if we've received skininfo that contains an
|
||||
//alternate bind matrix - if it does then apply the translational component
|
||||
//to the joints of the avatar.
|
||||
LLVOAvatar* pAvatarVO = vobj->getAvatar();
|
||||
bool pelvisGotSet = false;
|
||||
|
||||
if ( pAvatarVO )
|
||||
@@ -3504,13 +3549,16 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
if (type == LLDrawPool::POOL_ALPHA)
|
||||
{
|
||||
if (te->getFullbright())
|
||||
if (te->getColor().mV[3] > 0.f)
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
|
||||
if (te->getFullbright())
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (te->getShiny())
|
||||
@@ -3643,8 +3691,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
}
|
||||
else
|
||||
{
|
||||
drawablep->setState(LLDrawable::HAS_ALPHA);
|
||||
alpha_faces.push_back(facep);
|
||||
if (te->getColor().mV[3] > 0.f)
|
||||
{
|
||||
drawablep->setState(LLDrawable::HAS_ALPHA);
|
||||
alpha_faces.push_back(facep);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3761,6 +3812,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
}
|
||||
|
||||
mFaceList.clear();
|
||||
|
||||
if (pAvatarVO)
|
||||
{
|
||||
pAvatarVO->mAttachmentGeometryBytes += group->mGeometryBytes;
|
||||
pAvatarVO->mAttachmentSurfaceArea += group->mSurfaceArea;
|
||||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
|
||||
@@ -4102,6 +4159,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
|
||||
}
|
||||
}
|
||||
|
||||
group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize();
|
||||
|
||||
|
||||
buffer_map[mask][*face_iter].push_back(buffer);
|
||||
|
||||
//add face geometry
|
||||
|
||||
@@ -364,6 +364,7 @@ LLPipeline::LLPipeline() :
|
||||
mOldRenderDebugMask(0),
|
||||
mGroupQ1Locked(false),
|
||||
mGroupQ2Locked(false),
|
||||
mResetVertexBuffers(false),
|
||||
mLastRebuildPool(NULL),
|
||||
mAlphaPool(NULL),
|
||||
mSkyPool(NULL),
|
||||
@@ -591,6 +592,17 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
|
||||
{
|
||||
refreshCachedSettings();
|
||||
@@ -839,6 +851,7 @@ void LLPipeline::releaseScreenBuffers()
|
||||
{
|
||||
mScreen.release();
|
||||
mFXAABuffer.release();
|
||||
mPhysicsDisplay.release();
|
||||
mDeferredScreen.release();
|
||||
mDeferredDepth.release();
|
||||
mDeferredLight.release();
|
||||
@@ -3993,6 +4006,69 @@ 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);
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gDebugProgram.bind();
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
gGL.pushMatrix();
|
||||
gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix);
|
||||
bridge->renderPhysicsShapes();
|
||||
gGL.popMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gDebugProgram.unbind();
|
||||
}
|
||||
|
||||
mPhysicsDisplay.flush();
|
||||
}
|
||||
|
||||
|
||||
void LLPipeline::renderDebug()
|
||||
{
|
||||
LLMemType mt(LLMemType::MTYPE_PIPELINE);
|
||||
@@ -4956,7 +5032,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
|
||||
light_state->setConstantAttenuation(0.f);
|
||||
if (sRenderDeferred)
|
||||
{
|
||||
light_state->setLinearAttenuation(light_radius*1.5f);
|
||||
F32 size = light_radius*1.5f;
|
||||
light_state->setLinearAttenuation(size*size);
|
||||
light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
|
||||
}
|
||||
else
|
||||
@@ -6034,16 +6111,16 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
U32 res_mod = RenderResolutionDivisor;//.get();
|
||||
//U32 res_mod = RenderResolutionDivisor;//.get();
|
||||
|
||||
LLVector2 tc1(0,0);
|
||||
LLVector2 tc2((F32) mScreen.getWidth()*2,
|
||||
(F32) mScreen.getHeight()*2);
|
||||
|
||||
if (res_mod > 1)
|
||||
/*if (res_mod > 1)
|
||||
{
|
||||
tc2 /= (F32) res_mod;
|
||||
}
|
||||
}*/
|
||||
|
||||
LLFastTimer ftm(FTM_RENDER_BLOOM);
|
||||
gGL.color4f(1,1,1,1);
|
||||
@@ -6560,7 +6637,13 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
|
||||
mFXAABuffer.bindTexture(0, channel);
|
||||
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
|
||||
}
|
||||
|
||||
|
||||
gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
|
||||
gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
|
||||
gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
|
||||
gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
|
||||
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
|
||||
|
||||
F32 scale_x = (F32) width/mFXAABuffer.getWidth();
|
||||
F32 scale_y = (F32) height/mFXAABuffer.getHeight();
|
||||
shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
|
||||
@@ -6580,10 +6663,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res_mod > 1)
|
||||
/*if (res_mod > 1)
|
||||
{
|
||||
tc2 /= (F32) res_mod;
|
||||
}
|
||||
}*/
|
||||
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
|
||||
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
|
||||
@@ -6649,6 +6732,45 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
|
||||
}
|
||||
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
|
||||
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
|
||||
{
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gSplatTextureRectProgram.bind();
|
||||
}
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
|
||||
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::TRIANGLES);
|
||||
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();
|
||||
|
||||
if (LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
gSplatTextureRectProgram.unbind();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (LLRenderTarget::sUseFBO)
|
||||
{ //copy depth buffer from mScreen to framebuffer
|
||||
LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
|
||||
@@ -9094,7 +9216,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
|
||||
|
||||
assertInitialized();
|
||||
|
||||
BOOL muted = LLMuteList::getInstance()->isMuted(avatar->getID());
|
||||
bool muted = avatar->isVisuallyMuted();
|
||||
|
||||
pushRenderTypeMask();
|
||||
|
||||
|
||||
@@ -33,14 +33,14 @@
|
||||
#ifndef LL_PIPELINE_H
|
||||
#define LL_PIPELINE_H
|
||||
|
||||
#include "llcamera.h"
|
||||
#include "llerror.h"
|
||||
#include "lldarrayptr.h"
|
||||
#include "lldqueueptr.h"
|
||||
#include "llstat.h"
|
||||
#include "lldrawpool.h"
|
||||
#include "llspatialpartition.h"
|
||||
#include "m4math.h"
|
||||
#include "llmemory.h"
|
||||
#include "llpointer.h"
|
||||
#include "lldrawpool.h"
|
||||
#include "llgl.h"
|
||||
#include "lldrawable.h"
|
||||
@@ -48,6 +48,10 @@
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include <stack>
|
||||
|
||||
class LLViewerTexture;
|
||||
class LLEdge;
|
||||
class LLFace;
|
||||
@@ -118,7 +122,8 @@ public:
|
||||
|
||||
void allocateScreenBuffer(U32 resX, U32 resY);
|
||||
bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
|
||||
|
||||
void allocatePhysicsBuffer();
|
||||
|
||||
void resetVertexBuffers(LLDrawable* drawable);
|
||||
void generateImpostor(LLVOAvatar* avatar);
|
||||
void bindScreenToTexture();
|
||||
@@ -260,6 +265,7 @@ public:
|
||||
void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE);
|
||||
void renderHighlights();
|
||||
void renderDebug();
|
||||
void renderPhysicsDisplay();
|
||||
|
||||
void rebuildPools(); // Rebuild pools
|
||||
|
||||
@@ -424,30 +430,35 @@ public:
|
||||
|
||||
enum LLRenderDebugMask
|
||||
{
|
||||
RENDER_DEBUG_COMPOSITION = 0x0000001,
|
||||
RENDER_DEBUG_VERIFY = 0x0000002,
|
||||
RENDER_DEBUG_BBOXES = 0x0000004,
|
||||
RENDER_DEBUG_OCTREE = 0x0000008,
|
||||
RENDER_DEBUG_WIND_VECTORS = 0x0000010,
|
||||
RENDER_DEBUG_OCCLUSION = 0x0000020,
|
||||
RENDER_DEBUG_POINTS = 0x0000040,
|
||||
RENDER_DEBUG_TEXTURE_PRIORITY = 0x0000080,
|
||||
RENDER_DEBUG_TEXTURE_AREA = 0x0000100,
|
||||
RENDER_DEBUG_FACE_AREA = 0x0000200,
|
||||
RENDER_DEBUG_PARTICLES = 0x0000400,
|
||||
RENDER_DEBUG_GLOW = 0x0000800,
|
||||
RENDER_DEBUG_TEXTURE_ANIM = 0x0001000,
|
||||
RENDER_DEBUG_LIGHTS = 0x0002000,
|
||||
RENDER_DEBUG_BATCH_SIZE = 0x0004000,
|
||||
RENDER_DEBUG_ALPHA_BINS = 0x0008000,
|
||||
RENDER_DEBUG_RAYCAST = 0x0010000,
|
||||
RENDER_DEBUG_SHAME = 0x0020000,
|
||||
RENDER_DEBUG_SHADOW_FRUSTA = 0x0040000,
|
||||
RENDER_DEBUG_SCULPTED = 0x0080000,
|
||||
RENDER_DEBUG_AVATAR_VOLUME = 0x0100000,
|
||||
RENDER_DEBUG_BUILD_QUEUE = 0x0200000,
|
||||
RENDER_DEBUG_AGENT_TARGET = 0x0400000,
|
||||
RENDER_DEBUG_UPDATE_TYPE = 0x0800000,
|
||||
RENDER_DEBUG_COMPOSITION = 0x00000001,
|
||||
RENDER_DEBUG_VERIFY = 0x00000002,
|
||||
RENDER_DEBUG_BBOXES = 0x00000004,
|
||||
RENDER_DEBUG_OCTREE = 0x00000008,
|
||||
RENDER_DEBUG_WIND_VECTORS = 0x00000010,
|
||||
RENDER_DEBUG_OCCLUSION = 0x00000020,
|
||||
RENDER_DEBUG_POINTS = 0x00000040,
|
||||
RENDER_DEBUG_TEXTURE_PRIORITY = 0x00000080,
|
||||
RENDER_DEBUG_TEXTURE_AREA = 0x00000100,
|
||||
RENDER_DEBUG_FACE_AREA = 0x00000200,
|
||||
RENDER_DEBUG_PARTICLES = 0x00000400,
|
||||
RENDER_DEBUG_GLOW = 0x00000800,
|
||||
RENDER_DEBUG_TEXTURE_ANIM = 0x00001000,
|
||||
RENDER_DEBUG_LIGHTS = 0x00002000,
|
||||
RENDER_DEBUG_BATCH_SIZE = 0x00004000,
|
||||
RENDER_DEBUG_ALPHA_BINS = 0x00008000,
|
||||
RENDER_DEBUG_RAYCAST = 0x00010000,
|
||||
RENDER_DEBUG_SHAME = 0x00020000,
|
||||
RENDER_DEBUG_SHADOW_FRUSTA = 0x00040000,
|
||||
RENDER_DEBUG_SCULPTED = 0x00080000,
|
||||
RENDER_DEBUG_AVATAR_VOLUME = 0x00100000,
|
||||
RENDER_DEBUG_BUILD_QUEUE = 0x00200000,
|
||||
RENDER_DEBUG_AGENT_TARGET = 0x00400000,
|
||||
RENDER_DEBUG_UPDATE_TYPE = 0x00800000,
|
||||
RENDER_DEBUG_PHYSICS_SHAPES = 0x01000000,
|
||||
RENDER_DEBUG_NORMALS = 0x02000000,
|
||||
RENDER_DEBUG_LOD_INFO = 0x04000000,
|
||||
RENDER_DEBUG_RENDER_COMPLEXITY = 0x08000000,
|
||||
RENDER_DEBUG_ATTACHMENT_BYTES = 0x10000000,
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -470,6 +481,10 @@ public:
|
||||
S32 mNumVisibleNodes;
|
||||
S32 mVerticesRelit;
|
||||
|
||||
S32 mDebugTextureUploadCost;
|
||||
S32 mDebugSculptUploadCost;
|
||||
S32 mDebugMeshUploadCost;
|
||||
|
||||
S32 mLightingChanges;
|
||||
S32 mGeometryChanges;
|
||||
|
||||
@@ -516,6 +531,7 @@ public:
|
||||
LLRenderTarget mDeferredDepth;
|
||||
LLRenderTarget mDeferredLight;
|
||||
LLMultisampleBuffer mSampleBuffer;
|
||||
LLRenderTarget mPhysicsDisplay;
|
||||
|
||||
//utility buffer for rendering post effects, gets abused by renderDeferredLighting
|
||||
LLPointer<LLVertexBuffer> mDeferredVB;
|
||||
|
||||
Reference in New Issue
Block a user