Automated merge with file:///c:%5Ccode%5Cviewer-interesting-metrics

master
Richard Linden 2013-01-11 13:15:39 -08:00
commit a3d07fd4c2
51 changed files with 3981 additions and 1170 deletions

View File

@ -161,7 +161,7 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer)
// ---------------- test methods ----------------
S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius, const LLPlane* planes)
{
static const LLVector4a scaler[] = {
LLVector4a(-1,-1,-1),
@ -174,6 +174,12 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
LLVector4a( 1, 1, 1)
};
if(!planes)
{
//use agent space
planes = mAgentPlanes;
}
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
@ -183,7 +189,7 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
mask = mPlaneMask[i];
if (mask != 0xff)
{
const LLPlane& p(mAgentPlanes[i]);
const LLPlane& p(planes[i]);
p.getAt<3>(d);
rscale.setMul(radius, scaler[mask]);
minp.setSub(center, rscale);
@ -204,8 +210,14 @@ S32 LLCamera::AABBInFrustum(const LLVector4a &center, const LLVector4a& radius)
return result?1:2;
}
//exactly same as the function AABBInFrustum(...)
//except uses mRegionPlanes instead of mAgentPlanes.
S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius)
{
return AABBInFrustum(center, radius, mRegionPlanes);
}
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes)
{
static const LLVector4a scaler[] = {
LLVector4a(-1,-1,-1),
@ -218,6 +230,12 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
LLVector4a( 1, 1, 1)
};
if(!planes)
{
//use agent space
planes = mAgentPlanes;
}
U8 mask = 0;
bool result = false;
LLVector4a rscale, maxp, minp;
@ -227,7 +245,7 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
mask = mPlaneMask[i];
if ((i != 5) && (mask != 0xff))
{
const LLPlane& p(mAgentPlanes[i]);
const LLPlane& p(planes[i]);
p.getAt<3>(d);
rscale.setMul(radius, scaler[mask]);
minp.setSub(center, rscale);
@ -248,6 +266,13 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a&
return result?1:2;
}
//exactly same as the function AABBInFrustumNoFarClip(...)
//except uses mRegionPlanes instead of mAgentPlanes.
S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius)
{
return AABBInFrustumNoFarClip(center, radius, mRegionPlanes);
}
int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius)
{
LLVector3 dist = sphere_center-mFrustCenter;
@ -584,6 +609,23 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust)
}
}
//calculate regional planes from mAgentPlanes.
//vector "shift" is the vector of the region origin in the agent space.
void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift)
{
F32 d;
LLVector3 n;
for(S32 i = 0 ; i < 7; i++)
{
if (mPlaneMask[i] != 0xff)
{
n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]);
d = mAgentPlanes[i][3] - n * shift;
mRegionPlanes[i].setVec(n, d);
}
}
}
void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom)
{
LLVector3 a, b, c;

View File

@ -109,6 +109,7 @@ public:
private:
LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP
LL_ALIGN_16(LLPlane mRegionPlanes[7]); //frustum planes in a local region space, derived from mAgentPlanes
U8 mPlaneMask[8]; // 8 for alignment
F32 mView; // angle between top and bottom frustum planes in radians.
@ -178,6 +179,7 @@ public:
// Return number of bytes copied.
size_t readFrustumFromBuffer(const char *buffer);
void calcAgentFrustumPlanes(LLVector3* frust);
void calcRegionFrustumPlanes(const LLVector3& shift); //calculate regional planes from mAgentPlanes.
void ignoreAgentFrustumPlane(S32 idx);
// Returns 1 if partly in, 2 if fully in.
@ -186,8 +188,10 @@ public:
S32 sphereInFrustum(const LLVector3 &center, const F32 radius) const;
S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); }
S32 sphereInFrustumFull(const LLVector3 &center, const F32 radius) const { return sphereInFrustum(center, radius); }
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius);
S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL);
S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius);
//does a quick 'n dirty sphere-sphere check
S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius);

View File

@ -724,9 +724,14 @@ void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LL
gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
}
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color, const LLRectf& uv_rect)
{
if (NULL == image)
gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target);
}
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect, LLRenderTarget* target)
{
if (!image && !target)
{
llwarns << "image == NULL; aborting function" << llendl;
return;
@ -734,8 +739,14 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
LLGLSUIDefault gls_ui;
gGL.getTexUnit(0)->bind(image, true);
if(image != NULL)
{
gGL.getTexUnit(0)->bind(image, true);
}
else
{
gGL.getTexUnit(0)->bind(target);
}
gGL.color4fv(color.mV);
@ -788,7 +799,14 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
gGL.getTexUnit(0)->bind(image, true);
if(image != NULL)
{
gGL.getTexUnit(0)->bind(image, true);
}
else
{
gGL.getTexUnit(0)->bind(target);
}
gGL.color4fv(color.mV);

View File

@ -58,6 +58,7 @@ class LLUUID;
class LLWindow;
class LLView;
class LLHelp;
class LLRenderTarget;
// UI colors
extern const LLColor4 UI_VERTEX_COLOR;
@ -93,8 +94,9 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians,
void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), LLRenderTarget* target = NULL);
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f));
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f));

View File

@ -462,6 +462,7 @@ set(viewer_SOURCE_FILES
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llsaveoutfitcombobtn.cpp
llscenemonitor.cpp
llsceneview.cpp
llscreenchannel.cpp
llscriptfloater.cpp
@ -586,6 +587,7 @@ set(viewer_SOURCE_FILES
llviewernetwork.cpp
llviewerobject.cpp
llviewerobjectlist.cpp
llvieweroctree.cpp
llviewerparcelmedia.cpp
llviewerparcelmediaautoplay.cpp
llviewerparcelmgr.cpp
@ -1028,6 +1030,7 @@ set(viewer_HEADER_FILES
llrootview.h
llsavedsettingsglue.h
llsaveoutfitcombobtn.h
llscenemonitor.h
llsceneview.h
llscreenchannel.h
llscriptfloater.h
@ -1152,6 +1155,7 @@ set(viewer_HEADER_FILES
llviewernetwork.h
llviewerobject.h
llviewerobjectlist.h
llvieweroctree.h
llviewerparcelmedia.h
llviewerparcelmediaautoplay.h
llviewerparcelmgr.h

View File

@ -6389,6 +6389,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>ObjectCacheViewCullingEnabled</key>
<map>
<key>Comment</key>
<string>Enable the object cache view culling. Needs to restart viewer.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatAdvanced</key>
<map>
<key>Comment</key>
@ -9447,6 +9458,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>SceneLoadingMonitorEnabled</key>
<map>
<key>Comment</key>
<string>Enabled scene loading monitor if set</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ScriptHelpFollowsCursor</key>
<map>
<key>Comment</key>
@ -10853,7 +10875,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
<integer>0.0</integer>
<real>0.0</real>
</map>
<key>TextureFetchUpdateSkipLowPriority</key>
<map>
@ -12492,6 +12514,7 @@
<key>Type</key>
<string>LLSD</string>
<key>Value</key>
<array />
</map>
<key>VFSOldSize</key>
<map>

View File

@ -0,0 +1,49 @@
/**
* @file onetexturefilterF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2D tex0;
uniform float tolerance;
VARYING vec2 vary_texcoord0;
void main()
{
frag_color = texture2D(tex0, vary_texcoord0.xy);
if(frag_color[0] + frag_color[1] + frag_color[2] < tolerance)
{
discard;
}
else
{
frag_color[3] = 0.95f;
}
}

View File

@ -0,0 +1,38 @@
/**
* @file onetexturefilterV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
VARYING vec2 vary_texcoord0;
void main()
{
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_texcoord0 = texcoord0;
}

View File

@ -0,0 +1,41 @@
/**
* @file twotexturecompareF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
#else
#define frag_color gl_FragColor
#endif
uniform sampler2D tex0;
uniform sampler2D tex1;
VARYING vec2 vary_texcoord0;
VARYING vec2 vary_texcoord1;
void main()
{
frag_color = abs(texture2D(tex0, vary_texcoord0.xy) - texture2D(tex1, vary_texcoord0.xy));
}

View File

@ -0,0 +1,41 @@
/**
* @file twotexturecompareV.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
uniform mat4 modelview_projection_matrix;
ATTRIBUTE vec3 position;
ATTRIBUTE vec2 texcoord0;
ATTRIBUTE vec2 texcoord1;
VARYING vec2 vary_texcoord0;
VARYING vec2 vary_texcoord1;
void main()
{
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
vary_texcoord0 = texcoord0;
vary_texcoord1 = texcoord1;
}

View File

@ -3749,7 +3749,7 @@ U32 LLAppViewer::getObjectCacheVersion()
{
// Viewer object cache version, change if object update
// format changes. JC
const U32 INDRA_OBJECT_CACHE_VERSION = 14;
const U32 INDRA_OBJECT_CACHE_VERSION = 15;
return INDRA_OBJECT_CACHE_VERSION;
}
@ -4333,11 +4333,6 @@ void LLAppViewer::idle()
llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl;
gObjectList.mNumDeadObjectUpdates = 0;
}
if (gObjectList.mNumUnknownKills)
{
llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl;
gObjectList.mNumUnknownKills = 0;
}
if (gObjectList.mNumUnknownUpdates)
{
llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl;

View File

@ -40,7 +40,7 @@
#include "llsceneview.h"
#include "llviewertexture.h"
#include "llfloaterreg.h"
#include "llscenemonitor.h"
//
// Globals
//
@ -66,6 +66,7 @@ LLDebugView::~LLDebugView()
gDebugView = NULL;
gTextureView = NULL;
gSceneView = NULL;
gSceneMonitorView = NULL;
}
void LLDebugView::init()
@ -98,6 +99,13 @@ void LLDebugView::init()
gSceneView->setVisible(FALSE);
addChild(gSceneView);
gSceneView->setRect(rect);
gSceneMonitorView = new LLSceneMonitorView(r);
gSceneMonitorView->setFollowsTop();
gSceneMonitorView->setFollowsLeft();
gSceneMonitorView->setVisible(FALSE);
addChild(gSceneMonitorView);
gSceneMonitorView->setRect(rect);
r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
(S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));

View File

@ -49,6 +49,7 @@
#include "llspatialpartition.h"
#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llvocache.h"
const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;
const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
@ -76,7 +77,6 @@ LLTrace::MemStat LLDrawable::sMemStat("LLDrawable");
//
// static
U32 LLDrawable::sCurVisible = 0;
U32 LLDrawable::sNumZombieDrawables = 0;
F32 LLDrawable::sCurPixelAngle = 0;
LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList;
@ -86,33 +86,59 @@ LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList;
// static
void LLDrawable::incrementVisible()
{
sCurVisible++;
LLViewerOctreeEntryData::incrementVisible();
sCurPixelAngle = (F32) gViewerWindow->getWindowHeightRaw()/LLViewerCamera::getInstance()->getView();
}
void LLDrawable::init()
LLDrawable::LLDrawable(LLViewerObject *vobj, bool new_entry)
: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLDRAWABLE),
mVObjp(vobj)
{
init(new_entry);
}
void LLDrawable::init(bool new_entry)
{
// mXform
mParent = NULL;
mRenderType = 0;
mCurrentScale = LLVector3(1,1,1);
mDistanceWRTCamera = 0.0f;
mPositionGroup.clear();
mExtents[0].clear();
mExtents[1].clear();
mDistanceWRTCamera = 0.0f;
mState = 0;
mVObjp = NULL;
// mFaces
mSpatialGroupp = NULL;
mVisible = sCurVisible - 2;//invisible for the current frame and the last frame.
mRadius = 0.f;
mGeneration = -1;
mBinRadius = 1.f;
mBinIndex = -1;
// mFaces
mRadius = 0.f;
mGeneration = -1;
mSpatialBridge = NULL;
LLViewerOctreeEntry* entry = NULL;
LLVOCacheEntry* vo_entry = NULL;
if(!new_entry && mVObjp && getRegion() != NULL)
{
vo_entry = getRegion()->getCacheEntryForOctree(mVObjp->getLocalID());
if(vo_entry)
{
entry = vo_entry->getEntry();
}
}
setOctreeEntry(entry);
if(vo_entry)
{
if(!entry)
{
vo_entry->setOctreeEntry(mEntry);
}
else if(vo_entry->getNumOfChildren() > 0)
{
getRegion()->addVisibleCacheEntry(vo_entry); //to load all children.
}
getRegion()->addActiveCacheEntry(vo_entry);
}
llassert(!vo_entry || vo_entry->getEntry() == mEntry);
initVisible(sCurVisible - 2);//invisible for the current frame and the last frame.
}
// static
@ -156,6 +182,7 @@ void LLDrawable::markDead()
llwarns << "Warning! Marking dead multiple times!" << llendl;
return;
}
setState(DEAD);
if (mSpatialBridge)
{
@ -165,8 +192,7 @@ void LLDrawable::markDead()
sNumZombieDrawables++;
// We're dead. Free up all of our references to other objects
setState(DEAD);
// We're dead. Free up all of our references to other objects
cleanupReferences();
// sDeadList.put(this);
}
@ -220,6 +246,8 @@ void LLDrawable::cleanupReferences()
gPipeline.unlinkDrawable(this);
removeFromOctree();
{
LLFastTimer t(FTM_DEREF_DRAWABLE);
// Cleanup references to other objects
@ -228,6 +256,21 @@ void LLDrawable::cleanupReferences()
}
}
void LLDrawable::removeFromOctree()
{
if(!mEntry)
{
return;
}
mEntry->removeData(this);
if(mEntry->hasVOCacheEntry())
{
getRegion()->removeActiveCacheEntry((LLVOCacheEntry*)mEntry->getVOCacheEntry(), this);
}
mEntry = NULL;
}
void LLDrawable::cleanupDeadDrawables()
{
/*
@ -428,7 +471,13 @@ void LLDrawable::makeActive()
}
updatePartition();
}
else if (!isRoot() && !mParent->isActive()) //this should not happen, but occasionally it does...
{
mParent->makeActive();
//NOTE: linked set will now NEVER become static
mParent->setState(LLDrawable::ACTIVE_CHILD);
}
llassert(isAvatar() || isRoot() || mParent->isActive());
}
@ -717,7 +766,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
LLVOVolume* volume = getVOVolume();
if (volume)
{
if (getSpatialGroup())
if (getGroup())
{
pos.set(getPositionGroup().getF32ptr());
}
@ -835,9 +884,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector)
}
}
mExtents[0].add(shift_vector);
mExtents[1].add(shift_vector);
mPositionGroup.add(shift_vector);
shift(shift_vector);
}
else if (mSpatialBridge)
{
@ -845,9 +892,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector)
}
else if (isAvatar())
{
mExtents[0].add(shift_vector);
mExtents[1].add(shift_vector);
mPositionGroup.add(shift_vector);
shift(shift_vector);
}
mVObjp->onShift(shift_vector);
@ -859,40 +904,24 @@ const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const
return mXform.getPositionW();
}
const LLVector4a* LLDrawable::getSpatialExtents() const
{
return mExtents;
}
void LLDrawable::setSpatialExtents(const LLVector3& min, const LLVector3& max)
{
mExtents[0].load3(min.mV);
mExtents[1].load3(max.mV);
}
void LLDrawable::setSpatialExtents(const LLVector4a& min, const LLVector4a& max)
{
mExtents[0] = min;
mExtents[1] = max;
}
void LLDrawable::setPositionGroup(const LLVector4a& pos)
{
mPositionGroup = pos;
}
void LLDrawable::updateSpatialExtents()
{
if (mVObjp)
{
mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]);
const LLVector4a* exts = getSpatialExtents();
LLVector4a extents[2];
extents[0] = exts[0];
extents[1] = exts[1];
mVObjp->updateSpatialExtents(extents[0], extents[1]);
setSpatialExtents(extents[0], extents[1]);
}
updateBinRadius();
if (mSpatialBridge.notNull())
{
mPositionGroup.splat(0.f);
getGroupPosition().splat(0.f);
}
}
@ -901,11 +930,11 @@ void LLDrawable::updateBinRadius()
{
if (mVObjp.notNull())
{
mBinRadius = llmin(mVObjp->getBinRadius(), 256.f);
setBinRadius(llmin(mVObjp->getBinRadius(), 256.f));
}
else
{
mBinRadius = llmin(getRadius()*4.f, 256.f);
setBinRadius(llmin(getRadius()*4.f, 256.f));
}
}
@ -939,26 +968,56 @@ void LLDrawable::updateUVMinMax()
{
}
LLSpatialGroup* LLDrawable::getSpatialGroup() const
{
llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1);
return mSpatialGroupp;
//virtual
bool LLDrawable::isVisible() const
{
if (LLViewerOctreeEntryData::isVisible())
{
return true;
}
{
LLviewerOctreeGroup* group = mEntry->getGroup();
if (group && group->isVisible())
{
LLViewerOctreeEntryData::setVisible();
return true;
}
}
return false;
}
void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
//virtual
bool LLDrawable::isRecentlyVisible() const
{
//precondition: mSpatialGroupp MUST be null or DEAD or mSpatialGroupp MUST NOT contain this
llassert(!mSpatialGroupp || mSpatialGroupp->isDead() || !mSpatialGroupp->hasElement(this));
//currently visible or visible in the previous frame.
bool vis = LLViewerOctreeEntryData::isRecentlyVisible();
if(!vis)
{
LLviewerOctreeGroup* group = getGroup();
if (group && group->isRecentlyVisible())
{
LLViewerOctreeEntryData::setVisible();
vis = TRUE ;
}
}
return vis ;
}
void LLDrawable::setGroup(LLviewerOctreeGroup *groupp)
{
LLSpatialGroup* cur_groupp = (LLSpatialGroup*)getGroup();
//precondition: mGroupp MUST be null or DEAD or mGroupp MUST NOT contain this
//llassert(!cur_groupp || cur_groupp->isDead() || !cur_groupp->hasElement(this));
//precondition: groupp MUST be null or groupp MUST contain this
llassert(!groupp || groupp->hasElement(this));
llassert(!groupp || (LLSpatialGroup*)groupp->hasElement(this));
/*if (mSpatialGroupp && (groupp != mSpatialGroupp))
{
mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY);
}*/
if (mSpatialGroupp != groupp && getVOVolume())
if (cur_groupp != groupp && getVOVolume())
{ //NULL out vertex buffer references for volumes on spatial group change to maintain
//requirement that every face vertex buffer is either NULL or points to a vertex buffer
//contained by its drawable's spatial group
@ -974,10 +1033,10 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
//postcondition: if next group is NULL, previous group must be dead OR NULL OR binIndex must be -1
//postcondition: if next group is NOT NULL, binIndex must not be -1
llassert(groupp == NULL ? (mSpatialGroupp == NULL || mSpatialGroupp->isDead()) || getBinIndex() == -1 :
getBinIndex() != -1);
//llassert(groupp == NULL ? (cur_groupp == NULL || cur_groupp->isDead()) || (!getEntry() || getEntry()->getBinIndex() == -1) :
// (getEntry() && getEntry()->getBinIndex() != -1));
mSpatialGroupp = groupp;
LLViewerOctreeEntryData::setGroup(groupp);
}
LLSpatialPartition* LLDrawable::getSpatialPartition()
@ -996,11 +1055,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
{
if (mVObjp->isHUDAttachment())
{
setSpatialBridge(new LLHUDBridge(this));
setSpatialBridge(new LLHUDBridge(this, getRegion()));
}
else
{
setSpatialBridge(new LLVolumeBridge(this));
setSpatialBridge(new LLVolumeBridge(this, getRegion()));
}
}
return mSpatialBridge->asPartition();
@ -1019,89 +1078,26 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
return retval;
}
const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
//static
S32 LLDrawable::getMinVisFrameRange()
//virtual
S32 LLDrawable::getMinVisFrameRange() const
{
const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
return MIN_VIS_FRAME_RANGE ;
}
BOOL LLDrawable::isRecentlyVisible() const
{
//currently visible or visible in the previous frame.
BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ;
if(!vis)
{
LLSpatialGroup* group = getSpatialGroup();
if (group && group->isRecentlyVisible())
{
mVisible = sCurVisible;
vis = TRUE ;
}
}
return vis ;
}
BOOL LLDrawable::isVisible() const
{
if (mVisible == sCurVisible)
{
return TRUE;
}
#if 0
//disabling this code fixes DEV-20105. Leaving in place in case some other bug pops up as a a result.
//should be safe to just always ask the spatial group for visibility.
if (isActive())
{
if (isRoot())
{
LLSpatialGroup* group = mSpatialBridge.notNull() ? mSpatialBridge->getSpatialGroup() :
getSpatialGroup();
if (group && group->isVisible())
{
mVisible = sCurVisible;
return TRUE;
}
}
else
{
if (getParent()->isVisible())
{
mVisible = sCurVisible;
return TRUE;
}
}
}
else
#endif
{
LLSpatialGroup* group = getSpatialGroup();
if (group && group->isVisible())
{
mVisible = sCurVisible;
return TRUE;
}
}
return FALSE;
}
//=======================================
// Spatial Partition Bridging Drawable
//=======================================
LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask)
: LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB)
LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp) :
LLDrawable(root->getVObj(), true),
LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp)
{
mBridge = this;
mDrawable = root;
root->setSpatialBridge(this);
mBinIndex = -1;
mRenderType = mDrawable->mRenderType;
mDrawableType = mDrawable->mRenderType;
@ -1122,10 +1118,13 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat
LLSpatialBridge::~LLSpatialBridge()
{
LLSpatialGroup* group = getSpatialGroup();
if (group)
if(mEntry)
{
group->mSpatialPartition->remove(this, group);
LLSpatialGroup* group = getSpatialGroup();
if (group)
{
group->mSpatialPartition->remove(this, group);
}
}
//delete octree here so listeners will still be able to access bridge specific state
@ -1147,8 +1146,9 @@ void LLSpatialBridge::updateSpatialExtents()
root->rebound();
}
const LLVector4a* root_bounds = root->getBounds();
LLVector4a offset;
LLVector4a size = root->mBounds[1];
LLVector4a size = root_bounds[1];
//VECTORIZE THIS
LLMatrix4a mat;
@ -1160,7 +1160,7 @@ void LLSpatialBridge::updateSpatialExtents()
LLVector4a center;
mat.affineTransform(t, center);
mat.rotate(root->mBounds[0], offset);
mat.rotate(root_bounds[0], offset);
center.add(offset);
LLVector4a v[4];
@ -1182,12 +1182,9 @@ void LLSpatialBridge::updateSpatialExtents()
scale.mul(size);
mat.rotate(scale, v[3]);
LLVector4a& newMin = mExtents[0];
LLVector4a& newMax = mExtents[1];
newMin = newMax = center;
LLVector4a newMin;
LLVector4a newMax;
newMin = newMax = center;
for (U32 i = 0; i < 4; i++)
{
LLVector4a delta;
@ -1200,19 +1197,21 @@ void LLSpatialBridge::updateSpatialExtents()
newMin.setMin(newMin, min);
newMax.setMax(newMax, max);
}
setSpatialExtents(newMin, newMax);
LLVector4a diagonal;
diagonal.setSub(newMax, newMin);
mRadius = diagonal.getLength3().getF32() * 0.5f;
mPositionGroup.setAdd(newMin,newMax);
mPositionGroup.mul(0.5f);
LLVector4a& pos = getGroupPosition();
pos.setAdd(newMin,newMax);
pos.mul(0.5f);
updateBinRadius();
}
void LLSpatialBridge::updateBinRadius()
{
mBinRadius = llmin( mOctree->getSize()[0]*0.5f, 256.f);
setBinRadius(llmin( mOctree->getSize()[0]*0.5f, 256.f));
}
LLCamera LLSpatialBridge::transformCamera(LLCamera& camera)
@ -1247,7 +1246,7 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera)
void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select)
{
mVisible = sCurVisible;
LLViewerOctreeEntryData::setVisible();
#if 0 && !LL_RELEASE_FOR_DOWNLOAD
//crazy paranoid rules checking
@ -1282,21 +1281,21 @@ void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results,
#endif
}
class LLOctreeMarkNotCulled: public LLOctreeTraveler<LLDrawable>
class LLOctreeMarkNotCulled: public OctreeTraveler
{
public:
LLCamera* mCamera;
LLOctreeMarkNotCulled(LLCamera* camera_in) : mCamera(camera_in) { }
virtual void traverse(const LLOctreeNode<LLDrawable>* node)
virtual void traverse(const OctreeNode* node)
{
LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
group->setVisible();
LLOctreeTraveler<LLDrawable>::traverse(node);
OctreeTraveler::traverse(node);
}
void visit(const LLOctreeNode<LLDrawable>* branch)
void visit(const OctreeNode* branch)
{
gPipeline.markNotCulled((LLSpatialGroup*) branch->getListener(0), *mCamera);
}
@ -1340,7 +1339,7 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
}
if (!group ||
LLDrawable::getCurrentFrame() - av->mVisible > 1 ||
LLDrawable::getCurrentFrame() - av->getVisible() > 1 ||
impostor ||
!loaded)
{
@ -1354,16 +1353,17 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
group->rebound();
LLVector4a center;
center.setAdd(mExtents[0], mExtents[1]);
const LLVector4a* exts = getSpatialExtents();
center.setAdd(exts[0], exts[1]);
center.mul(0.5f);
LLVector4a size;
size.setSub(mExtents[1], mExtents[0]);
size.setSub(exts[1], exts[0]);
size.mul(0.5f);
if ((LLPipeline::sShadowRender && camera_in.AABBInFrustum(center, size)) ||
LLPipeline::sImpostorRender ||
(camera_in.AABBInFrustumNoFarClip(center, size) &&
AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist)))
AABBSphereIntersect(exts[0], exts[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist)))
{
if (!LLPipeline::sImpostorRender &&
!LLPipeline::sShadowRender &&
@ -1478,9 +1478,7 @@ BOOL LLSpatialBridge::updateMove()
void LLSpatialBridge::shiftPos(const LLVector4a& vec)
{
mExtents[0].add(vec);
mExtents[1].add(vec);
mPositionGroup.add(vec);
LLDrawable::shift(vec);
}
void LLSpatialBridge::cleanupReferences()
@ -1488,11 +1486,8 @@ void LLSpatialBridge::cleanupReferences()
LLDrawable::cleanupReferences();
if (mDrawable)
{
/*
mDrawable->setGroup(NULL);
DON'T DO THIS -- this should happen through octree destruction
mDrawable->setSpatialGroup(NULL);
if (mDrawable->getVObj())
{
LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren();
@ -1503,10 +1498,10 @@ void LLSpatialBridge::cleanupReferences()
LLDrawable* drawable = child->mDrawable;
if (drawable)
{
drawable->setSpatialGroup(NULL);
}
drawable->setGroup(NULL);
}
}*/
}
}
LLDrawable* drawablep = mDrawable;
mDrawable = NULL;
@ -1575,8 +1570,8 @@ void LLDrawable::updateFaceSize(S32 idx)
}
}
LLBridgePartition::LLBridgePartition()
: LLSpatialPartition(0, FALSE, 0)
LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp)
: LLSpatialPartition(0, FALSE, 0, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
@ -1584,8 +1579,8 @@ LLBridgePartition::LLBridgePartition()
mSlopRatio = 0.25f;
}
LLHUDBridge::LLHUDBridge(LLDrawable* drawablep)
: LLVolumeBridge(drawablep)
LLHUDBridge::LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
: LLVolumeBridge(drawablep, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_HUD;
mPartitionType = LLViewerRegion::PARTITION_HUD;

View File

@ -42,6 +42,7 @@
#include "llviewerobject.h"
#include "llrect.h"
#include "llappviewer.h" // for gFrameTimeSeconds
#include "llvieweroctree.h"
class LLCamera;
class LLDrawPool;
@ -60,11 +61,11 @@ const U32 SILHOUETTE_HIGHLIGHT = 0;
// All data for new renderer goes into this class.
LL_ALIGN_PREFIX(16)
class LLDrawable
: public LLRefCount,
public LLTrace::MemTrackable<LLDrawable, 16>
: public LLViewerOctreeEntryData,
public LLTrace::MemTrackable<LLDrawable>
{
public:
LLDrawable(const LLDrawable& rhs)
LLDrawable(const LLDrawable& rhs) : LLViewerOctreeEntryData(rhs)
{
*this = rhs;
}
@ -77,7 +78,7 @@ public:
static void initClass();
LLDrawable() { init(); }
LLDrawable(LLViewerObject *vobj, bool new_entry = false);
void markDead(); // Mark this drawable as dead
BOOL isDead() const { return isState(DEAD); }
@ -85,11 +86,9 @@ public:
BOOL isLight() const;
BOOL isVisible() const;
BOOL isRecentlyVisible() const;
virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE);
LLSpatialGroup* getSpatialGroup()const {return (LLSpatialGroup*)getGroup();}
LLViewerRegion* getRegion() const { return mVObjp->getRegion(); }
const LLTextureEntry* getTextureEntry(U8 which) const { return mVObjp->getTE(which); }
LLPointer<LLViewerObject>& getVObj() { return mVObjp; }
@ -102,16 +101,12 @@ public:
const LLVector3& getPosition() const { return mXform.getPosition(); }
const LLVector3& getWorldPosition() const { return mXform.getPositionW(); }
const LLVector3 getPositionAgent() const;
const LLVector4a& getPositionGroup() const { return mPositionGroup; }
const LLVector3& getScale() const { return mCurrentScale; }
void setScale(const LLVector3& scale) { mCurrentScale = scale; }
const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); }
const LLQuaternion& getRotation() const { return mXform.getRotation(); }
F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); }
S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; }
F32 getBinRadius() const { return mBinRadius; }
S32 getBinIndex() const { return mBinIndex; }
void setBinIndex(S32 index) const { mBinIndex = index; }
void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); }
LLXformMatrix* getXform() { return &mXform; }
@ -142,7 +137,7 @@ public:
void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep);
void mergeFaces(LLDrawable* src);
void init();
void init(bool new_entry);
void destroy();
void update();
@ -173,8 +168,12 @@ public:
BOOL getLit() const { return isState(UNLIT) ? FALSE : TRUE; }
void setLit(BOOL lit) { lit ? clearState(UNLIT) : setState(UNLIT); }
bool isVisible() const;
bool isRecentlyVisible() const;
virtual void cleanupReferences();
void setGroup(LLviewerOctreeGroup* group);
void setRadius(const F32 radius);
F32 getRadius() const { return mRadius; }
F32 getVisibilityRadius() const;
@ -184,11 +183,6 @@ public:
const LLVector3& getBounds(LLVector3& min, LLVector3& max) const;
virtual void updateSpatialExtents();
virtual void updateBinRadius();
const LLVector4a* getSpatialExtents() const;
void setSpatialExtents(const LLVector3& min, const LLVector3& max);
void setSpatialExtents(const LLVector4a& min, const LLVector4a& max);
void setPositionGroup(const LLVector4a& pos);
void setRenderType(S32 type) { mRenderType = type; }
BOOL isRenderType(S32 type) { return mRenderType == type; }
@ -197,10 +191,14 @@ public:
// Debugging methods
S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators...
void setSpatialGroup(LLSpatialGroup *groupp);
LLSpatialGroup *getSpatialGroup() const;
LLSpatialPartition* getSpatialPartition();
virtual S32 getMinVisFrameRange()const;
void removeFromOctree();
void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; }
// Statics
static void incrementVisible();
static void cleanupDeadDrawables();
@ -285,10 +283,6 @@ public:
ACTIVE_CHILD = 0x40000000,
} EDrawableFlags;
private: //aligned members
LL_ALIGN_16(LLVector4a mExtents[2]);
LL_ALIGN_16(LLVector4a mPositionGroup);
public:
LLXformMatrix mXform;
@ -297,12 +291,6 @@ public:
F32 mDistanceWRTCamera;
static S32 getCurrentFrame() { return sCurVisible; }
static S32 getMinVisFrameRange();
void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; }
static F32 sCurPixelAngle; //current pixels per radian
static LLTrace::MemStat sMemStat;
@ -313,18 +301,13 @@ private:
S32 mRenderType;
LLPointer<LLViewerObject> mVObjp;
face_list_t mFaces;
LLSpatialGroup* mSpatialGroupp;
LLPointer<LLDrawable> mSpatialBridge;
mutable U32 mVisible;
F32 mRadius;
F32 mBinRadius;
mutable S32 mBinIndex;
S32 mGeneration;
LLVector3 mCurrentScale;
static U32 sCurVisible; // Counter for what value of mVisible means currently visible
static U32 sNumZombieDrawables;
static LLDynamicArrayPtr<LLPointer<LLDrawable> > sDeadList;
} LL_ALIGN_POSTFIX(16);

View File

@ -0,0 +1,460 @@
/**
* @file llscenemonitor.cpp
* @brief monitor the scene loading process.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llrendertarget.h"
#include "llscenemonitor.h"
#include "llviewerwindow.h"
#include "llviewerdisplay.h"
#include "llviewercontrol.h"
#include "llviewershadermgr.h"
#include "llui.h"
#include "llstartup.h"
#include "llappviewer.h"
#include "llwindow.h"
#include "llpointer.h"
#include "llspatialpartition.h"
LLSceneMonitorView* gSceneMonitorView = NULL;
//
//The procedures of monitoring when the scene finishes loading visually,
//i.e., no pixel differences among frames, are:
//1, freeze all dynamic objects and avatars;
//2, (?) disable all sky and water;
//3, capture frames periodically, by calling "capture()";
//4, compute pixel differences between two latest captured frames, by calling "compare()", results are stored at mDiff;
//5, compute the number of pixels in mDiff above some tolerance threshold in GPU, by calling "queryDiff() -> calcDiffAggregate()";
//6, use gl occlusion query to fetch the result from GPU, by calling "fetchQueryResult()";
//END.
//
LLSceneMonitor::LLSceneMonitor() :
mEnabled(FALSE),
mDiff(NULL),
mDiffResult(0.f),
mDiffTolerance(0.1f),
mCurTarget(NULL),
mNeedsUpdateDiff(FALSE),
mHasNewDiff(FALSE),
mHasNewQueryResult(FALSE),
mDebugViewerVisible(FALSE),
mQueryObject(0),
mSamplingTime(1.0f),
mDiffPixelRatio(0.5f)
{
mFrames[0] = NULL;
mFrames[1] = NULL;
}
LLSceneMonitor::~LLSceneMonitor()
{
destroyClass();
}
void LLSceneMonitor::destroyClass()
{
reset();
}
void LLSceneMonitor::reset()
{
delete mFrames[0];
delete mFrames[1];
delete mDiff;
mFrames[0] = NULL;
mFrames[1] = NULL;
mDiff = NULL;
mCurTarget = NULL;
unfreezeScene();
if(mQueryObject > 0)
{
release_occlusion_query_object_name(mQueryObject);
mQueryObject = 0;
}
}
void LLSceneMonitor::setDebugViewerVisible(BOOL visible)
{
mDebugViewerVisible = visible;
}
bool LLSceneMonitor::preCapture()
{
static LLCachedControl<bool> monitor_enabled(gSavedSettings,"SceneLoadingMonitorEnabled");
static LLFrameTimer timer;
mCurTarget = NULL;
if (!LLGLSLShader::sNoFixedFunction)
{
return false;
}
BOOL enabled = (BOOL)monitor_enabled || mDebugViewerVisible;
if(mEnabled != enabled)
{
if(mEnabled)
{
reset();
unfreezeScene();
}
else
{
freezeScene();
}
mEnabled = enabled;
}
if(!mEnabled)
{
return false;
}
if(timer.getElapsedTimeF32() < mSamplingTime)
{
return false;
}
timer.reset();
S32 width = gViewerWindow->getWorldViewWidthRaw();
S32 height = gViewerWindow->getWorldViewHeightRaw();
if(!mFrames[0])
{
mFrames[0] = new LLRenderTarget();
mFrames[0]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true);
gGL.getTexUnit(0)->bind(mFrames[0]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
mCurTarget = mFrames[0];
}
else if(!mFrames[1])
{
mFrames[1] = new LLRenderTarget();
mFrames[1]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true);
gGL.getTexUnit(0)->bind(mFrames[1]);
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
mCurTarget = mFrames[1];
}
else //swap
{
mCurTarget = mFrames[0];
mFrames[0] = mFrames[1];
mFrames[1] = mCurTarget;
}
if(mCurTarget->getWidth() != width || mCurTarget->getHeight() != height) //size changed
{
mCurTarget->resize(width, height, GL_RGB);
}
return true;
}
void LLSceneMonitor::freezeAvatar(LLCharacter* avatarp)
{
mAvatarPauseHandles.push_back(avatarp->requestPause());
}
void LLSceneMonitor::freezeScene()
{
//freeze all avatars
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
{
freezeAvatar((LLCharacter*)(*iter));
}
// freeze everything else
gSavedSettings.setBOOL("FreezeTime", TRUE);
}
void LLSceneMonitor::unfreezeScene()
{
//thaw all avatars
mAvatarPauseHandles.clear();
// thaw everything else
gSavedSettings.setBOOL("FreezeTime", FALSE);
}
void LLSceneMonitor::capture()
{
static U32 last_capture_time = 0;
if(last_capture_time == gFrameCount)
{
return;
}
last_capture_time = gFrameCount;
preCapture();
if(!mCurTarget)
{
return;
}
U32 old_FBO = LLRenderTarget::sCurFBO;
gGL.getTexUnit(0)->bind(mCurTarget);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); //point to the main frame buffer.
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, mCurTarget->getWidth(), mCurTarget->getHeight()); //copy the content
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, old_FBO);
mCurTarget = NULL;
mNeedsUpdateDiff = TRUE;
}
bool LLSceneMonitor::needsUpdate() const
{
return mNeedsUpdateDiff;
}
void LLSceneMonitor::compare()
{
if(!mNeedsUpdateDiff)
{
return;
}
mNeedsUpdateDiff = FALSE;
if(!mFrames[0] || !mFrames[1])
{
return;
}
if(mFrames[0]->getWidth() != mFrames[1]->getWidth() || mFrames[0]->getHeight() != mFrames[1]->getHeight())
{
return; //size does not match
}
S32 width = gViewerWindow->getWindowWidthRaw();
S32 height = gViewerWindow->getWindowHeightRaw();
if(!mDiff)
{
mDiff = new LLRenderTarget();
mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true);
}
else if(mDiff->getWidth() != width || mDiff->getHeight() != height)
{
mDiff->resize(width, height, GL_RGBA);
}
mDiff->bindTarget();
mDiff->clear();
gTwoTextureCompareProgram.bind();
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(0)->bind(mFrames[0]);
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(1)->bind(mFrames[1]);
gGL.getTexUnit(1)->activate();
gl_rect_2d_simple_tex(width, height);
mDiff->flush();
gTwoTextureCompareProgram.unbind();
gGL.getTexUnit(0)->disable();
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(1)->disable();
gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
mHasNewDiff = TRUE;
//send out the query request.
queryDiff();
}
void LLSceneMonitor::queryDiff()
{
if(mDebugViewerVisible)
{
return;
}
calcDiffAggregate();
}
//calculate Diff aggregate information in GPU, and enable gl occlusion query to capture it.
void LLSceneMonitor::calcDiffAggregate()
{
if(!mHasNewDiff && !mDebugViewerVisible)
{
return;
}
if(!mQueryObject)
{
mQueryObject = get_new_occlusion_query_object_name();
}
LLGLDepthTest depth(true, false, GL_ALWAYS);
if(!mDebugViewerVisible)
{
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
}
LLGLSLShader* cur_shader = NULL;
cur_shader = LLGLSLShader::sCurBoundShaderPtr;
gOneTextureFilterProgram.bind();
gOneTextureFilterProgram.uniform1f("tolerance", mDiffTolerance);
if(mHasNewDiff)
{
glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryObject);
}
gl_draw_scaled_target(0, 0, S32(mDiff->getWidth() * mDiffPixelRatio), S32(mDiff->getHeight() * mDiffPixelRatio), mDiff);
if(mHasNewDiff)
{
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
mHasNewDiff = FALSE;
mHasNewQueryResult = TRUE;
}
gOneTextureFilterProgram.unbind();
if(cur_shader != NULL)
{
cur_shader->bind();
}
if(!mDebugViewerVisible)
{
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
void LLSceneMonitor::fetchQueryResult()
{
if(!mHasNewQueryResult)
{
return;
}
mHasNewQueryResult = FALSE;
GLuint available = 0;
glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_AVAILABLE_ARB, &available);
if(!available)
{
return;
}
GLuint count = 0;
glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_ARB, &count);
mDiffResult = count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio); //0.5 -> (front face + back face)
//llinfos << count << " : " << mDiffResult << llendl;
}
//-------------------------------------------------------------------------------------------------------------
//definition of class LLSceneMonitorView
//-------------------------------------------------------------------------------------------------------------
LLSceneMonitorView::LLSceneMonitorView(const LLRect& rect)
: LLFloater(LLSD())
{
setRect(rect);
setVisible(FALSE);
setCanMinimize(false);
setCanClose(true);
}
void LLSceneMonitorView::onClickCloseBtn()
{
setVisible(false);
}
void LLSceneMonitorView::setVisible(BOOL visible)
{
LLSceneMonitor::getInstance()->setDebugViewerVisible(visible);
LLView::setVisible(visible);
}
void LLSceneMonitorView::draw()
{
const LLRenderTarget* target = LLSceneMonitor::getInstance()->getDiffTarget();
if(!target)
{
return;
}
F32 ratio = LLSceneMonitor::getInstance()->getDiffPixelRatio();
S32 height = (S32)(target->getHeight() * ratio);
S32 width = (S32)(target->getWidth() * ratio);
//S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.5f);
//S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.5f);
LLRect new_rect;
new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height);
setRect(new_rect);
//draw background
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
LLSceneMonitor::getInstance()->calcDiffAggregate();
//show some texts
LLColor4 color = LLColor4::white;
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
S32 lines = 0;
std::string num_str = llformat("Frame difference: %.6f", LLSceneMonitor::getInstance()->getDiffResult());
LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP);
lines++;
num_str = llformat("Pixel tolerance: (R+G+B) < %.4f", LLSceneMonitor::getInstance()->getDiffTolerance());
LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP);
lines++;
num_str = llformat("Sampling time: %.3f seconds", LLSceneMonitor::getInstance()->getSamplingTime());
LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP);
LLView::draw();
}

View File

@ -0,0 +1,106 @@
/**
* @file llscenemonitor.h
* @brief monitor the process of scene loading
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLSCENE_MONITOR_H
#define LL_LLSCENE_MONITOR_H
#include "llsingleton.h"
#include "llmath.h"
#include "llfloater.h"
#include "llcharacter.h"
class LLCharacter;
class LLRenderTarget;
class LLSceneMonitor : public LLSingleton<LLSceneMonitor>
{
public:
LLSceneMonitor();
~LLSceneMonitor();
void destroyClass();
void freezeAvatar(LLCharacter* avatarp);
void setDebugViewerVisible(BOOL visible);
void capture(); //capture the main frame buffer
void compare(); //compare the stored two buffers.
void queryDiff();
void fetchQueryResult();
void calcDiffAggregate();
void setDiffTolerance(F32 tol) {mDiffTolerance = tol;}
const LLRenderTarget* getDiffTarget() const {return mDiff;}
F32 getDiffTolerance() const {return mDiffTolerance;}
F32 getDiffResult() const { return mDiffResult;}
F32 getSamplingTime() const { return mSamplingTime;}
F32 getDiffPixelRatio() const { return mDiffPixelRatio;}
bool isEnabled()const {return mEnabled;}
bool needsUpdate() const;
private:
void freezeScene();
void unfreezeScene();
void reset();
bool preCapture();
private:
BOOL mEnabled;
BOOL mNeedsUpdateDiff;
BOOL mHasNewDiff;
BOOL mHasNewQueryResult;
BOOL mDebugViewerVisible;
LLRenderTarget* mFrames[2];
LLRenderTarget* mDiff;
LLRenderTarget* mCurTarget;
GLuint mQueryObject; //used for glQuery
F32 mDiffResult; //aggregate results of mDiff.
F32 mDiffTolerance; //pixels are filtered out when R+G+B < mDiffTolerance
F32 mSamplingTime; //time interval to capture frames, in seconds
F32 mDiffPixelRatio; //ratio of pixels used for comparison against the original mDiff size along one dimension
std::vector<LLAnimPauseRequest> mAvatarPauseHandles;
};
class LLSceneMonitorView : public LLFloater
{
public:
LLSceneMonitorView(const LLRect& rect);
virtual void draw();
virtual void setVisible(BOOL visible);
protected:
virtual void onClickCloseBtn();
};
extern LLSceneMonitorView* gSceneMonitorView;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -45,22 +45,21 @@
#define SG_STATE_INHERIT_MASK (OCCLUDED)
#define SG_INITIAL_STATE_MASK (DIRTY | GEOM_DIRTY)
class LLViewerOctreePartition;
class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
class LLTextureAtlas;
class LLTextureAtlasSlot;
class LLViewerRegion;
S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared);
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared);
void pushVerts(LLFace* face, U32 mask);
// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera
U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center);
U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center);
GLuint get_new_occlusion_query_object_name();
void release_occlusion_query_object_name(GLuint name);
class LLDrawInfo : public LLRefCount
{
@ -192,13 +191,13 @@ public:
};
LL_ALIGN_PREFIX(16)
class LLSpatialGroup : public LLOctreeListener<LLDrawable>
class LLSpatialGroup : public LLviewerOctreeGroup
{
friend class LLSpatialPartition;
friend class LLOctreeStateCheck;
public:
LLSpatialGroup(const LLSpatialGroup& rhs)
LLSpatialGroup(const LLSpatialGroup& rhs) : LLviewerOctreeGroup(rhs)
{
*this = rhs;
}
@ -229,16 +228,7 @@ public:
typedef std::map<U32, drawmap_elem_t > draw_map_t;
typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t;
typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t;
typedef std::map<U32, buffer_texture_map_t> buffer_map_t;
typedef LLOctreeListener<LLDrawable> BaseType;
typedef LLOctreeListener<LLDrawable> OctreeListener;
typedef LLTreeNode<LLDrawable> TreeNode;
typedef LLOctreeNode<LLDrawable> OctreeNode;
typedef LLOctreeRoot<LLDrawable> OctreeRoot;
typedef LLOctreeTraveler<LLDrawable> OctreeTraveler;
typedef LLOctreeNode<LLDrawable>::element_iter element_iter;
typedef LLOctreeNode<LLDrawable>::element_list element_list;
typedef std::map<U32, buffer_texture_map_t> buffer_map_t;
struct CompareDistanceGreater
{
@ -275,18 +265,15 @@ public:
typedef enum
{
DEAD = 0x00000001,
DIRTY = 0x00000002,
OBJECT_DIRTY = 0x00000004,
GEOM_DIRTY = 0x00000008,
ALPHA_DIRTY = 0x00000010,
SKIP_FRUSTUM_CHECK = 0x00000020,
IN_IMAGE_QUEUE = 0x00000040,
IMAGE_DIRTY = 0x00000080,
MESH_DIRTY = 0x00000100,
NEW_DRAWINFO = 0x00000200,
IN_BUILD_Q1 = 0x00000400,
IN_BUILD_Q2 = 0x00000800,
DEAD = LLviewerOctreeGroup::INVALID_STATE,
GEOM_DIRTY = (DEAD << 1),
ALPHA_DIRTY = (GEOM_DIRTY << 1),
IN_IMAGE_QUEUE = (ALPHA_DIRTY << 1),
IMAGE_DIRTY = (IN_IMAGE_QUEUE << 1),
MESH_DIRTY = (IMAGE_DIRTY << 1),
NEW_DRAWINFO = (MESH_DIRTY << 1),
IN_BUILD_Q1 = (NEW_DRAWINFO << 1),
IN_BUILD_Q2 = (IN_BUILD_Q1 << 1),
STATE_MASK = 0x0000FFFF,
} eSpatialState;
@ -301,12 +288,8 @@ public:
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
BOOL isHUDGroup() ;
BOOL isDead() { return isState(DEAD); }
BOOL isState(U32 state) const;
BOOL isDead() { return hasState(DEAD); }
BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; }
U32 getState() { return mState; }
void setState(U32 state);
void clearState(U32 state);
void clearDrawMap();
void validate();
@ -315,23 +298,18 @@ public:
void setState(U32 state, S32 mode);
void clearState(U32 state, S32 mode);
void clearState(U32 state) {mState &= ~state;}
void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE);
LLSpatialGroup* getParent();
BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE);
BOOL addObject(LLDrawable *drawablep);
BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE);
BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group
BOOL isVisible() const;
BOOL isRecentlyVisible() const;
void setVisible();
void shift(const LLVector4a &offset);
BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax);
void unbound();
BOOL rebound();
void checkOcclusion(); //read back last occlusion query (if any)
void doOcclusion(LLCamera* camera); //issue occlusion query
void destroyGL(bool keep_occlusion = false);
@ -343,28 +321,18 @@ public:
void rebuildGeom();
void rebuildMesh();
void setState(U32 state) {mState |= state;}
void dirtyGeom() { setState(GEOM_DIRTY); }
void dirtyMesh() { setState(MESH_DIRTY); }
//octree wrappers to make code more readable
element_list& getData() { return mOctreeNode->getData(); }
element_iter getDataBegin() { return mOctreeNode->getDataBegin(); }
element_iter getDataEnd() { return mOctreeNode->getDataEnd(); }
bool hasElement(LLDrawable* drawablep) { return std::find(mOctreeNode->getDataBegin(), mOctreeNode->getDataEnd(), drawablep) != mOctreeNode->getDataEnd(); }
U32 getElementCount() const { return mOctreeNode->getElementCount(); }
bool isEmpty() const { return mOctreeNode->isEmpty(); }
void dirtyMesh() { setState(MESH_DIRTY); }
void drawObjectBox(LLColor4 col);
//LISTENER FUNCTIONS
virtual void handleInsertion(const TreeNode* node, LLDrawable* face);
virtual void handleRemoval(const TreeNode* node, LLDrawable* face);
virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face);
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face);
virtual void handleDestruction(const TreeNode* node);
virtual void handleStateChange(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child);
//-------------------
//for atlas use
//-------------------
@ -386,21 +354,6 @@ public:
public:
typedef enum
{
BOUNDS = 0,
EXTENTS = 2,
OBJECT_BOUNDS = 4,
OBJECT_EXTENTS = 6,
VIEW_ANGLE = 8,
LAST_VIEW_ANGLE = 9,
V4_COUNT = 10
} eV4Index;
LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects)
LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children
LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node
LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node
LL_ALIGN_16(LLVector4a mViewAngle);
LL_ALIGN_16(LLVector4a mLastUpdateViewAngle);
@ -421,7 +374,6 @@ private:
protected:
virtual ~LLSpatialGroup();
U32 mState;
U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS];
U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS];
@ -436,7 +388,6 @@ public:
F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node
F32 mBuilt;
OctreeNode* mOctreeNode;
LLSpatialPartition* mSpatialPartition;
LLPointer<LLVertexBuffer> mVertexBuffer;
@ -444,8 +395,7 @@ public:
U32 mBufferUsage;
draw_map_t mDrawMap;
S32 mVisible[LLViewerCamera::NUM_CAMERAS];
F32 mDistance;
F32 mDepth;
F32 mLastUpdateDistance;
@ -468,10 +418,10 @@ public:
virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
};
class LLSpatialPartition: public LLGeometryManager
class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManager
{
public:
LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage);
LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage, LLViewerRegion* regionp);
virtual ~LLSpatialPartition();
LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE);
@ -498,7 +448,8 @@ public:
virtual void rebuildMesh(LLSpatialGroup* group);
BOOL visibleObjectsInFrustum(LLCamera& camera);
S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum
/*virtual*/ S32 cull(LLCamera &camera); // Cull on arbitrary frustum
S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select); // Cull on arbitrary frustum
BOOL isVisible(const LLVector3& v);
bool isHUDPartition() ;
@ -513,23 +464,21 @@ public:
void resetVertexBuffers();
BOOL isOcclusionEnabled();
BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax);
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;
U32 mDrawableType;
const BOOL mRenderByGroup;
U32 mLODSeed;
U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed)
U32 mVertexDataMask;
F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25);
BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
U32 mDrawableType;
U32 mPartitionType;
BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering
};
// class for creating bridges between spatial partitions
@ -541,7 +490,7 @@ protected:
public:
typedef std::vector<LLPointer<LLSpatialBridge> > bridge_vector_t;
LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask);
LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp);
void destroyTree();
@ -564,7 +513,7 @@ public:
};
class LLCullResult
class LLCullResult
{
public:
LLCullResult();
@ -663,7 +612,7 @@ private:
class LLWaterPartition : public LLSpatialPartition
{
public:
LLWaterPartition();
LLWaterPartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group) { }
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
};
@ -672,14 +621,14 @@ public:
class LLVoidWaterPartition : public LLWaterPartition
{
public:
LLVoidWaterPartition();
LLVoidWaterPartition(LLViewerRegion* regionp);
};
//spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp)
class LLTerrainPartition : public LLSpatialPartition
{
public:
LLTerrainPartition();
LLTerrainPartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group);
virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage);
};
@ -688,7 +637,7 @@ public:
class LLTreePartition : public LLSpatialPartition
{
public:
LLTreePartition();
LLTreePartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group) { }
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
@ -698,7 +647,7 @@ public:
class LLParticlePartition : public LLSpatialPartition
{
public:
LLParticlePartition();
LLParticlePartition(LLViewerRegion* regionp);
virtual void rebuildGeom(LLSpatialGroup* group);
virtual void getGeometry(LLSpatialGroup* group);
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count);
@ -710,14 +659,14 @@ protected:
class LLHUDParticlePartition : public LLParticlePartition
{
public:
LLHUDParticlePartition();
LLHUDParticlePartition(LLViewerRegion* regionp);
};
//spatial partition for grass (implemented in LLVOGrass.cpp)
class LLGrassPartition : public LLSpatialPartition
{
public:
LLGrassPartition();
LLGrassPartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group);
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count);
protected:
@ -747,7 +696,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager
{
public:
LLVolumePartition();
LLVolumePartition(LLViewerRegion* regionp);
virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); }
virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); }
virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); }
@ -758,7 +707,7 @@ public:
class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager
{
public:
LLVolumeBridge(LLDrawable* drawable);
LLVolumeBridge(LLDrawable* drawable, LLViewerRegion* regionp);
virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); }
virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); }
virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); }
@ -768,7 +717,7 @@ public:
class LLHUDBridge : public LLVolumeBridge
{
public:
LLHUDBridge(LLDrawable* drawablep);
LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
virtual void shiftPos(const LLVector4a& vec);
virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera);
};
@ -777,7 +726,7 @@ public:
class LLBridgePartition : public LLSpatialPartition
{
public:
LLBridgePartition();
LLBridgePartition(LLViewerRegion* regionp);
virtual void getGeometry(LLSpatialGroup* group) { }
virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { }
};
@ -785,7 +734,7 @@ public:
class LLHUDPartition : public LLBridgePartition
{
public:
LLHUDPartition();
LLHUDPartition(LLViewerRegion* regionp);
virtual void shift(const LLVector4a &offset);
};

View File

@ -2358,6 +2358,10 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpMetricsHeaders = new LLCore::HttpHeaders;
mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml");
mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
//reset the texture timer.
gTextureTimer.reset();
gTextureTimer.pause();
}
LLTextureFetch::~LLTextureFetch()

View File

@ -49,6 +49,8 @@
#include "llviewertexturelist.h"
#include "llvovolume.h"
#include "llviewerstats.h"
#include "llworld.h"
#include "llviewerobjectlist.h"
// For avatar texture view
#include "llvoavatarself.h"
@ -517,6 +519,9 @@ void LLGLTexMemBar::draw()
LLUnit<LLUnits::Bytes, F32> total_texture_downloaded = gTotalTextureData;
LLUnit<LLUnits::Bytes, F32> total_object_downloaded = gTotalObjectData;
U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
U32 total_active_cached_objects = LLWorld::getInstance()->getNumOfActiveCachedObjects();
U32 total_objects = gObjectList.getNumObjects();
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
@ -549,9 +554,11 @@ void LLGLTexMemBar::draw()
U32 cache_read(0U), cache_write(0U), res_wait(0U);
LLAppViewer::getTextureFetch()->getStateStats(&cache_read, &cache_write, &res_wait);
text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d Cread: %u Cwrite: %u Rwait: %u",
text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB #Objs/#Cached: %d/%d Tot Htp: %d Cread: %u Cwrite: %u Rwait: %u",
total_texture_downloaded.value(),
total_object_downloaded.value(),
total_objects,
total_active_cached_objects,
total_http_requests,
cache_read,
cache_write,

View File

@ -77,6 +77,7 @@
#include "llwlparammanager.h"
#include "llwaterparammanager.h"
#include "llpostprocess.h"
#include "llscenemonitor.h"
extern LLPointer<LLViewerTexture> gStartTexture;
extern bool gShiftFrame;
@ -991,6 +992,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
LLPipeline::sUnderWaterRender = FALSE;
{
//capture the frame buffer.
LLSceneMonitor::getInstance()->capture();
}
LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
if (!for_snapshot)
{
@ -1224,6 +1230,15 @@ void render_ui(F32 zoom_factor, int subfield)
glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
}
if(LLSceneMonitor::getInstance()->needsUpdate())
{
gGL.pushMatrix();
gViewerWindow->setup2DRender();
LLSceneMonitor::getInstance()->compare();
gViewerWindow->setup3DRender();
gGL.popMatrix();
}
{
BOOL to_texture = gPipeline.canUseVertexShaders() &&
LLPipeline::sRenderGlow;

View File

@ -122,6 +122,7 @@
#include "llwindow.h"
#include "llpathfindingmanager.h"
#include "boost/unordered_map.hpp"
#include "llscenemonitor.h"
using namespace LLVOAvatarDefines;
@ -529,7 +530,10 @@ class LLAdvancedToggleConsole : public view_listener_t
{
toggle_visibility( (void*)gSceneView);
}
else if ("scene monitor" == console_type)
{
toggle_visibility( (void*)gSceneMonitorView);
}
#if MEM_TRACK_MEM
else if ("memory view" == console_type)
{
@ -557,9 +561,9 @@ class LLAdvancedCheckConsole : public view_listener_t
{
new_value = LLFloaterReg::instanceVisible("fast_timers");
}
else if ("scene view" == console_type)
else if ("scene monitor" == console_type)
{
new_value = get_visibility( (void*) gSceneView);
new_value = get_visibility( (void*) gSceneMonitorView);
}
#if MEM_TRACK_MEM
else if ("memory view" == console_type)

View File

@ -4483,30 +4483,42 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_
static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Kill Objects");
const U32 KILLOBJECT_DELETE_OPCODE = 0;
void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
{
LLFastTimer t(FTM_PROCESS_OBJECTS);
LLUUID id;
U32 local_id;
S32 i;
S32 num_objects;
LLUUID id;
num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
for (i = 0; i < num_objects; i++)
U32 ip = mesgsys->getSenderIP();
U32 port = mesgsys->getSenderPort();
LLViewerRegion* regionp = NULL;
{
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
LLHost host(ip, port);
regionp = LLWorld::getInstance()->getRegion(host);
}
LLViewerObjectList::getUUIDFromLocal(id,
local_id,
gMessageSystem->getSenderIP(),
gMessageSystem->getSenderPort());
bool delete_object = false;
S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
for (S32 i = 0; i < num_objects; ++i)
{
U32 local_id;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
if (local_id == KILLOBJECT_DELETE_OPCODE)
{
// This local_id is invalid, but was sent by the server to flag
// all subsequent local_id's as objects that were actually deleted
// rather than unsubscribed from interestlist.
delete_object = true;
continue;
}
LLViewerObjectList::getUUIDFromLocal(id, local_id, ip, port);
if (id == LLUUID::null)
{
LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL;
gObjectList.mNumUnknownKills++;
continue;
}
else
@ -4514,34 +4526,35 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL;
}
// ...don't kill the avatar
if (!(id == gAgentID))
if (id == gAgentID)
{
LLViewerObject *objectp = gObjectList.findObject(id);
if (objectp)
{
// Display green bubble on kill
if ( gShowObjectUpdates )
{
LLColor4 color(0.f,1.f,0.f,1.f);
gPipeline.addDebugBlip(objectp->getPositionAgent(), color);
}
// never kill our avatar
continue;
}
// Do the kill
gObjectList.killObject(objectp);
}
else
LLViewerObject *objectp = gObjectList.findObject(id);
if (objectp)
{
// Display green bubble on kill
if ( gShowObjectUpdates )
{
LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL;
gObjectList.mNumUnknownKills++;
LLColor4 color(0.f,1.f,0.f,1.f);
gPipeline.addDebugBlip(objectp->getPositionAgent(), color);
}
// Do the kill
gObjectList.killObject(objectp);
}
if(delete_object)
{
regionp->killCacheEntry(local_id);
}
// We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab,
// which is using the object, release the mouse capture correctly when the object dies.
// See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical().
LLSelectMgr::getInstance()->removeObjectFromSelections(id);
}
}

View File

@ -100,6 +100,7 @@
#include "lltrans.h"
#include "llsdutil.h"
#include "llmediaentry.h"
#include "llvocache.h"
//#define DEBUG_UPDATE_TYPE
@ -326,6 +327,22 @@ void LLViewerObject::deleteTEImages()
mTEImages = NULL;
}
//if enabled, add this object to vo cache tree when removed from rendering.
void LLViewerObject::EnableToCacheTree(bool enabled)
{
if(mDrawable.notNull() && mDrawable->getEntry() && mDrawable->getEntry()->hasVOCacheEntry())
{
if(enabled)
{
((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->addState(LLVOCacheEntry::ADD_TO_CACHE_TREE);
}
else
{
((LLVOCacheEntry*)mDrawable->getEntry()->getVOCacheEntry())->clearState(LLVOCacheEntry::ADD_TO_CACHE_TREE);
}
}
}
void LLViewerObject::markDead()
{
if (!mDead)
@ -348,7 +365,7 @@ void LLViewerObject::markDead()
childp = mChildList.back();
if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
{
//llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
//llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
childp->setParent(NULL); // LLViewerObject::markDead 1
childp->markDead();
}
@ -889,10 +906,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
}
// Coordinates of objects on simulators are region-local.
U64 region_handle;
mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
U64 region_handle = 0;
if(mesgsys != NULL)
{
mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
if(regionp != mRegionp && regionp && mRegionp)//region cross
{
@ -918,11 +936,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
return retval;
}
U16 time_dilation16;
mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
F32 time_dilation = ((F32) time_dilation16) / 65535.f;
mTimeDilation = time_dilation;
mRegionp->setTimeDilation(time_dilation);
if(mesgsys != NULL)
{
U16 time_dilation16;
mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
F32 time_dilation = ((F32) time_dilation16) / 65535.f;
mTimeDilation = time_dilation;
mRegionp->setTimeDilation(time_dilation);
}
// this will be used to determine if we've really changed position
// Use getPosition, not getPositionRegion, since this is what we're comparing directly against.
@ -1695,13 +1716,16 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// Preload these five flags for every object.
// Finer shades require the object to be selected, and the selection manager
// stores the extended permission info.
U32 flags;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
// keep local flags and overwrite remote-controlled flags
mFlags = (mFlags & FLAGS_LOCAL) | flags;
if(mesgsys != NULL)
{
U32 flags;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
// keep local flags and overwrite remote-controlled flags
mFlags = (mFlags & FLAGS_LOCAL) | flags;
// ...new objects that should come in selected need to be added to the selected list
mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
}
}
break;
@ -1729,10 +1753,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
// No parent now, new parent in message -> attach to that parent if possible
LLUUID parent_uuid;
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
if(mesgsys != NULL)
{
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
parent_id,
mesgsys->getSenderIP(),
mesgsys->getSenderPort());
}
else
{
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
parent_id,
mRegionp->getHost().getAddress(),
mRegionp->getHost().getPort());
}
LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid);
@ -1808,9 +1843,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
//
//parent_id
U32 ip = mesgsys->getSenderIP();
U32 port = mesgsys->getSenderPort();
U32 ip, port;
if(mesgsys != NULL)
{
ip = mesgsys->getSenderIP();
port = mesgsys->getSenderPort();
}
else
{
ip = mRegionp->getHost().getAddress();
port = mRegionp->getHost().getPort();
}
gObjectList.orphanize(this, parent_id, ip, port);
// Hide particles, icon and HUD
@ -1848,10 +1892,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
else
{
LLUUID parent_uuid;
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
if(mesgsys != NULL)
{
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
parent_id,
gMessageSystem->getSenderIP(),
gMessageSystem->getSenderPort());
}
else
{
LLViewerObjectList::getUUIDFromLocal(parent_uuid,
parent_id,
mRegionp->getHost().getAddress(),
mRegionp->getHost().getPort());
}
sent_parentp = gObjectList.findObject(parent_uuid);
if (isAvatar())
@ -1872,8 +1927,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Switching parents, but we don't know the new parent.
//
U32 ip = mesgsys->getSenderIP();
U32 port = mesgsys->getSenderPort();
U32 ip, port;
if(mesgsys != NULL)
{
ip = mesgsys->getSenderIP();
port = mesgsys->getSenderPort();
}
else
{
ip = mRegionp->getHost().getAddress();
port = mRegionp->getHost().getPort();
}
// We're an orphan, flag things appropriately.
gObjectList.orphanize(this, parent_id, ip, port);
@ -1957,7 +2022,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.normQuat();
if (sPingInterpolate)
if (sPingInterpolate && mesgsys != NULL)
{
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
if (cdp)
@ -1980,16 +2045,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// If we're going to skip this message, why are we
// doing all the parenting, etc above?
U32 packet_id = mesgsys->getCurrentRecvPacketID();
if (packet_id < mLatestRecvPacketID &&
mLatestRecvPacketID - packet_id < 65536)
if(mesgsys != NULL)
{
//skip application of this message, it's old
return retval;
U32 packet_id = mesgsys->getCurrentRecvPacketID();
if (packet_id < mLatestRecvPacketID &&
mLatestRecvPacketID - packet_id < 65536)
{
//skip application of this message, it's old
return retval;
}
mLatestRecvPacketID = packet_id;
}
mLatestRecvPacketID = packet_id;
// Set the change flags for scale
if (new_scale != getScale())
{

View File

@ -136,6 +136,7 @@ public:
BOOL isDead() const {return mDead;}
BOOL isOrphaned() const { return mOrphaned; }
BOOL isParticleSource() const;
void EnableToCacheTree(bool enabled);
virtual LLVOAvatar* asAvatar();

View File

@ -76,6 +76,7 @@
#include "object_flags.h"
#include "llappviewer.h"
#include "llvocache.h"
extern F32 gMinObjectDistance;
extern BOOL gAnimateTextures;
@ -106,7 +107,6 @@ LLViewerObjectList::LLViewerObjectList()
mNumNewObjects = 0;
mWasPaused = FALSE;
mNumDeadObjectUpdates = 0;
mNumUnknownKills = 0;
mNumUnknownUpdates = 0;
}
@ -228,9 +228,15 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
U32 i,
const EObjectUpdateType update_type,
LLDataPacker* dpp,
BOOL just_created)
bool just_created,
bool from_cache)
{
LLMessageSystem* msg = gMessageSystem;
LLMessageSystem* msg = NULL;
if(!from_cache)
{
msg = gMessageSystem;
}
// ignore returned flags
objectp->processUpdateMessage(msg, user_data, i, update_type, dpp);
@ -254,7 +260,18 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
// RN: this must be called after we have a drawable
// (from gPipeline.addObject)
// so that the drawable parent is set properly
findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
if(msg != NULL)
{
findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort());
}
else
{
LLViewerRegion* regionp = objectp->getRegion();
if(regionp != NULL)
{
findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort());
}
}
// If we're just wandering around, don't create new objects selected.
if (just_created
@ -277,10 +294,88 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp,
static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects");
LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp)
{
LLDataPacker *cached_dpp = entry->getDP();
if (!cached_dpp)
{
return NULL; //nothing cached.
}
LLViewerObject *objectp;
U32 local_id;
LLPCode pcode = 0;
LLUUID fullid;
LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
// Cache Hit.
cached_dpp->reset();
cached_dpp->unpackUUID(fullid, "ID");
cached_dpp->unpackU32(local_id, "LocalID");
cached_dpp->unpackU8(pcode, "PCode");
objectp = findObject(fullid);
if (objectp)
{
if(!objectp->isDead() && (objectp->mLocalID != entry->getLocalID() ||
objectp->getRegion() != regionp))
{
removeFromLocalIDTable(objectp);
setUUIDAndLocal(fullid, entry->getLocalID(),
regionp->getHost().getAddress(),
regionp->getHost().getPort());
if (objectp->mLocalID != entry->getLocalID())
{ // Update local ID in object with the one sent from the region
objectp->mLocalID = entry->getLocalID();
}
if (objectp->getRegion() != regionp)
{ // Object changed region, so update it
objectp->updateRegion(regionp); // for LLVOAvatar
}
}
else
{
return objectp; //already loaded.
}
}
bool justCreated = false;
if (!objectp)
{
objectp = createObjectFromCache(pcode, regionp, fullid, entry->getLocalID());
if (!objectp)
{
llinfos << "createObject failure for object: " << fullid << llendl;
recorder.objectUpdateFailure(entry->getLocalID(), OUT_FULL_CACHED, 0);
return NULL;
}
justCreated = true;
mNumNewObjects++;
sCacheHitRate.sample(100.f);
}
if (objectp->isDead())
{
llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl;
}
processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true);
recorder.log(0.2f);
LLVOAvatar::cullAvatarsByPixelArea();
return objectp;
}
void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type,
bool cached, bool compressed)
bool compressed)
{
LLFastTimer t(FTM_PROCESS_OBJECTS);
@ -299,7 +394,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
// I don't think this case is ever hit. TODO* Test this.
if (!cached && !compressed && update_type != OUT_FULL)
if (!compressed && update_type != OUT_FULL)
{
//llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl;
gTerseObjectUpdates += num_objects;
@ -343,7 +438,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compressed_dpbuffer[2048];
LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
LLDataPacker *cached_dpp = NULL;
LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
for (i = 0; i < num_objects; i++)
@ -353,43 +447,10 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
BOOL justCreated = FALSE;
S32 msg_size = 0;
if (cached)
if (compressed)
{
U32 id;
U32 crc;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
msg_size += sizeof(U32) * 2;
// Lookup data packer and add this id to cache miss lists if necessary.
U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
cached_dpp = regionp->getDP(id, crc, cache_miss_type);
if (cached_dpp)
{
// Cache Hit.
cached_dpp->reset();
cached_dpp->unpackUUID(fullid, "ID");
cached_dpp->unpackU32(local_id, "LocalID");
cached_dpp->unpackU8(pcode, "PCode");
}
else
{
// Cache Miss.
recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
continue; // no data packer, skip this object
}
}
else if (compressed)
{
S32 uncompressed_length = 2048;
compressed_dp.reset();
U32 flags = 0;
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
}
S32 uncompressed_length = 2048;
compressed_dp.reset();
uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data);
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
@ -485,9 +546,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
continue;
}
}
else if (cached) // Cache hit only?
{
}
else
{
if (update_type != OUT_FULL)
@ -520,8 +578,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
}
justCreated = TRUE;
mNumNewObjects++;
sCacheHitRate.sample(cached ? 100.f : 0.f);
}
@ -540,16 +596,17 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated);
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{
bCached = true;
LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size);
U32 flags = 0;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i);
if(!(flags & FLAGS_TEMPORARY_ON_REZ))
{
bCached = true;
LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp);
recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size);
}
}
}
else if (cached) // Cache hit only?
{
objectp->mLocalID = local_id;
processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated);
}
else
{
if (update_type == OUT_FULL)
@ -572,14 +629,51 @@ void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type)
{
processObjectUpdate(mesgsys, user_data, update_type, false, true);
processObjectUpdate(mesgsys, user_data, update_type, true);
}
void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys,
void **user_data,
const EObjectUpdateType update_type)
{
processObjectUpdate(mesgsys, user_data, update_type, true, false);
//processObjectUpdate(mesgsys, user_data, update_type, true, false);
S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData);
gFullObjectUpdates += num_objects;
U64 region_handle;
mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
if (!regionp)
{
llwarns << "Object update from unknown region! " << region_handle << llendl;
return;
}
LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
for (S32 i = 0; i < num_objects; i++)
{
S32 msg_size = 0;
U32 id;
U32 crc;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i);
msg_size += sizeof(U32) * 2;
// Lookup data packer and add this id to cache miss lists if necessary.
U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
if(!regionp->probeCache(id, crc, cache_miss_type))
{
// Cache Miss.
recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
continue; // no data packer, skip this object
}
sCacheHitRate.sample(100.f);
}
return;
}
void LLViewerObjectList::dirtyAllObjectInventory()
@ -1230,7 +1324,7 @@ void LLViewerObjectList::removeDrawable(LLDrawable* drawablep)
}
}
BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
BOOL LLViewerObjectList::killObject(LLViewerObject *objectp, bool cache_enabled)
{
// Don't ever kill gAgentAvatarp, just force it to the agent's region
// unless region is NULL which is assumed to mean you are logging out.
@ -1245,16 +1339,8 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp)
if (objectp)
{
if (objectp->isDead())
{
// This object is already dead. Don't need to do more.
return TRUE;
}
else
{
objectp->markDead();
}
objectp->EnableToCacheTree(cache_enabled); //enable to add to VO cache tree if set.
objectp->markDead(); // does the right thing if object already dead
return TRUE;
}
@ -1890,7 +1976,30 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi
return objectp;
}
LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id)
{
llassert_always(uuid.notNull());
LLViewerObject *objectp = LLViewerObject::createObject(uuid, pcode, regionp);
if (!objectp)
{
// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl;
return NULL;
}
objectp->mLocalID = local_id;
mUUIDObjectMap[uuid] = objectp;
setUUIDAndLocal(uuid,
local_id,
regionp->getHost().getAddress(),
regionp->getHost().getPort());
mObjects.push_back(objectp);
updateActive(objectp);
return objectp;
}
LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp,
const LLUUID &uuid, const U32 local_id, const LLHost &sender)
{

View File

@ -40,6 +40,7 @@
class LLCamera;
class LLNetMap;
class LLDebugBeacon;
class LLVOCacheEntry;
const U32 CLOSE_BIN_SIZE = 10;
const U32 NUM_BINS = 128;
@ -65,12 +66,13 @@ public:
inline LLViewerObject *findObject(const LLUUID &id);
LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp); // Create a viewer-side object
LLViewerObject *createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id);
LLViewerObject *createObject(const LLPCode pcode, LLViewerRegion *regionp,
const LLUUID &uuid, const U32 local_id, const LLHost &sender);
LLViewerObject *replaceObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); // TomY: hack to switch VO instances on the fly
BOOL killObject(LLViewerObject *objectp);
BOOL killObject(LLViewerObject *objectp, bool cache_enabled = false);
void killObjects(LLViewerRegion *regionp); // Kill all objects owned by a particular region.
void killAllObjects();
void removeDrawable(LLDrawable* drawablep);
@ -78,8 +80,10 @@ public:
void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list.
// Simulator and viewer side object updates...
void processUpdateCore(LLViewerObject* objectp, void** data, U32 block, const EObjectUpdateType update_type, LLDataPacker* dpp, BOOL justCreated);
void processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type, bool cached=false, bool compressed=false);
void processUpdateCore(LLViewerObject* objectp, void** data, U32 block, const EObjectUpdateType update_type,
LLDataPacker* dpp, bool justCreated, bool from_cache = false);
LLViewerObject* processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp);
void processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type, bool compressed=false);
void processCompressedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type);
void processCachedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type);
void updateApparentAngles(LLAgent &agent);
@ -188,7 +192,6 @@ public:
S32 mNumUnknownUpdates;
S32 mNumDeadObjectUpdates;
S32 mNumUnknownKills;
S32 mNumDeadObjects;
protected:
std::vector<U64> mOrphanParents; // LocalID/ip,port of orphaned objects

View File

@ -0,0 +1,800 @@
/**
* @file llvieweroctree.cpp
* @brief LLViewerOctreeGroup class implementation and supporting functions
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llvieweroctree.h"
#include "llviewerregion.h"
//-----------------------------------------------------------------------------------
//static variables definitions
//-----------------------------------------------------------------------------------
U32 LLViewerOctreeEntryData::sCurVisible = 0;
//-----------------------------------------------------------------------------------
//some global functions definitions
//-----------------------------------------------------------------------------------
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
{
return AABBSphereIntersectR2(min, max, origin, rad*rad);
}
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &r)
{
F32 d = 0.f;
F32 t;
if ((min-origin).magVecSquared() < r &&
(max-origin).magVecSquared() < r)
{
return 2;
}
for (U32 i = 0; i < 3; i++)
{
if (origin.mV[i] < min.mV[i])
{
t = min.mV[i] - origin.mV[i];
d += t*t;
}
else if (origin.mV[i] > max.mV[i])
{
t = origin.mV[i] - max.mV[i];
d += t*t;
}
if (d > r)
{
return 0;
}
}
return 1;
}
S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad)
{
return AABBSphereIntersectR2(min, max, origin, rad*rad);
}
S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &r)
{
F32 d = 0.f;
F32 t;
LLVector4a origina;
origina.load3(origin.mV);
LLVector4a v;
v.setSub(min, origina);
if (v.dot3(v) < r)
{
v.setSub(max, origina);
if (v.dot3(v) < r)
{
return 2;
}
}
for (U32 i = 0; i < 3; i++)
{
if (origin.mV[i] < min[i])
{
t = min[i] - origin.mV[i];
d += t*t;
}
else if (origin.mV[i] > max[i])
{
t = origin.mV[i] - max[i];
d += t*t;
}
if (d > r)
{
return 0;
}
}
return 1;
}
//-----------------------------------------------------------------------------------
//class LLViewerOctreeEntry definitions
//-----------------------------------------------------------------------------------
LLViewerOctreeEntry::LLViewerOctreeEntry()
: mGroup(NULL),
mBinRadius(0.f),
mBinIndex(-1)
{
mPositionGroup.clear();
mExtents[0].clear();
mExtents[1].clear();
for(S32 i = 0; i < NUM_DATA_TYPE; i++)
{
mData[i] = NULL;
}
}
LLViewerOctreeEntry::~LLViewerOctreeEntry()
{
llassert(!mGroup);
}
void LLViewerOctreeEntry::addData(LLViewerOctreeEntryData* data)
{
//llassert(mData[data->getDataType()] == NULL);
llassert(data != NULL);
mData[data->getDataType()] = data;
}
void LLViewerOctreeEntry::removeData(LLViewerOctreeEntryData* data)
{
//llassert(data->getDataType() != LLVOCACHEENTRY); //can not remove VOCache entry
if(!mData[data->getDataType()])
{
return;
}
mData[data->getDataType()] = NULL;
if(mGroup != NULL && !mData[LLDRAWABLE])
{
LLviewerOctreeGroup* group = mGroup;
mGroup = NULL;
group->removeFromGroup(data);
llassert(mBinIndex == -1);
}
}
//called by group handleDestruction() ONLY when group is destroyed by octree.
void LLViewerOctreeEntry::nullGroup()
{
mGroup = NULL;
}
void LLViewerOctreeEntry::setGroup(LLviewerOctreeGroup* group)
{
if(mGroup == group)
{
return;
}
if(mGroup)
{
LLviewerOctreeGroup* group = mGroup;
mGroup = NULL;
group->removeFromGroup(this);
llassert(mBinIndex == -1);
}
mGroup = group;
}
//-----------------------------------------------------------------------------------
//class LLViewerOctreeEntryData definitions
//-----------------------------------------------------------------------------------
LLViewerOctreeEntryData::~LLViewerOctreeEntryData()
{
if(mEntry)
{
mEntry->removeData(this);
}
}
LLViewerOctreeEntryData::LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryDataType_t data_type)
: mDataType(data_type),
mEntry(NULL)
{
}
//virtual
void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry)
{
if(mEntry.notNull())
{
return;
}
if(!entry)
{
mEntry = new LLViewerOctreeEntry();
}
else
{
mEntry = entry;
}
mEntry->addData(this);
}
void LLViewerOctreeEntryData::setSpatialExtents(const LLVector3& min, const LLVector3& max)
{
mEntry->mExtents[0].load3(min.mV);
mEntry->mExtents[1].load3(max.mV);
}
void LLViewerOctreeEntryData::setSpatialExtents(const LLVector4a& min, const LLVector4a& max)
{
mEntry->mExtents[0] = min;
mEntry->mExtents[1] = max;
}
void LLViewerOctreeEntryData::setPositionGroup(const LLVector4a& pos)
{
mEntry->mPositionGroup = pos;
}
const LLVector4a* LLViewerOctreeEntryData::getSpatialExtents() const
{
return mEntry->getSpatialExtents();
}
//virtual
void LLViewerOctreeEntryData::setGroup(LLviewerOctreeGroup* group)
{
mEntry->setGroup(group);
}
void LLViewerOctreeEntryData::shift(const LLVector4a &shift_vector)
{
mEntry->mExtents[0].add(shift_vector);
mEntry->mExtents[1].add(shift_vector);
mEntry->mPositionGroup.add(shift_vector);
}
LLviewerOctreeGroup* LLViewerOctreeEntryData::getGroup()const
{
return mEntry.notNull() ? mEntry->mGroup : NULL;
}
const LLVector4a& LLViewerOctreeEntryData::getPositionGroup() const
{
return mEntry->getPositionGroup();
}
//virtual
bool LLViewerOctreeEntryData::isVisible() const
{
if(mEntry)
{
return mEntry->mVisible == sCurVisible;
}
return false;
}
//virtual
bool LLViewerOctreeEntryData::isRecentlyVisible() const
{
if(!mEntry)
{
return false;
}
if(isVisible())
{
return true;
}
if(getGroup() && getGroup()->isRecentlyVisible())
{
setVisible();
return true;
}
return (sCurVisible - mEntry->mVisible < getMinVisFrameRange());
}
void LLViewerOctreeEntryData::setVisible() const
{
if(mEntry)
{
mEntry->mVisible = sCurVisible;
}
}
//-----------------------------------------------------------------------------------
//class LLviewerOctreeGroup definitions
//-----------------------------------------------------------------------------------
LLviewerOctreeGroup::~LLviewerOctreeGroup()
{
if(LLViewerRegion::sCurRegionp && isVisible())
{
LLViewerRegion::sCurRegionp->clearVisibleGroup(this);
}
}
LLviewerOctreeGroup::LLviewerOctreeGroup(OctreeNode* node) :
mOctreeNode(node),
mState(CLEAN)
{
LLVector4a tmp;
tmp.splat(0.f);
mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] =
mObjectExtents[0] = mObjectExtents[1] = tmp;
mBounds[0] = node->getCenter();
mBounds[1] = node->getSize();
mOctreeNode->addListener(this);
}
bool LLviewerOctreeGroup::hasElement(LLViewerOctreeEntryData* data)
{
if(!data->getEntry())
{
return false;
}
return std::find(getDataBegin(), getDataEnd(), data->getEntry()) != getDataEnd();
}
bool LLviewerOctreeGroup::removeFromGroup(LLViewerOctreeEntryData* data)
{
return removeFromGroup(data->getEntry());
}
bool LLviewerOctreeGroup::removeFromGroup(LLViewerOctreeEntry* entry)
{
llassert(entry != NULL);
llassert(!entry->getGroup());
unbound();
if (mOctreeNode)
{
if (!mOctreeNode->remove(entry))
{
OCT_ERRS << "Could not remove LLVOCacheEntry from LLVOCacheOctreeGroup" << llendl;
return false;
}
}
setState(OBJECT_DIRTY);
return true;
}
//virtual
void LLviewerOctreeGroup::unbound()
{
if (isDirty())
{
return;
}
setState(DIRTY);
//all the parent nodes need to rebound this child
if (mOctreeNode)
{
OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent();
while (parent != NULL)
{
LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) parent->getListener(0);
if (!group || group->isDirty())
{
return;
}
group->setState(DIRTY);
parent = (OctreeNode*) parent->getParent();
}
}
}
//virtual
void LLviewerOctreeGroup::rebound()
{
if (!isDirty())
{
return;
}
if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
{
LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) mOctreeNode->getChild(0)->getListener(0);
group->rebound();
//copy single child's bounding box
mBounds[0] = group->mBounds[0];
mBounds[1] = group->mBounds[1];
mExtents[0] = group->mExtents[0];
mExtents[1] = group->mExtents[1];
group->setState(SKIP_FRUSTUM_CHECK);
}
else if (mOctreeNode->isLeaf())
{ //copy object bounding box if this is a leaf
boundObjects(TRUE, mExtents[0], mExtents[1]);
mBounds[0] = mObjectBounds[0];
mBounds[1] = mObjectBounds[1];
}
else
{
LLVector4a& newMin = mExtents[0];
LLVector4a& newMax = mExtents[1];
LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) mOctreeNode->getChild(0)->getListener(0);
group->clearState(SKIP_FRUSTUM_CHECK);
group->rebound();
//initialize to first child
newMin = group->mExtents[0];
newMax = group->mExtents[1];
//first, rebound children
for (U32 i = 1; i < mOctreeNode->getChildCount(); i++)
{
group = (LLviewerOctreeGroup*) mOctreeNode->getChild(i)->getListener(0);
group->clearState(SKIP_FRUSTUM_CHECK);
group->rebound();
const LLVector4a& max = group->mExtents[1];
const LLVector4a& min = group->mExtents[0];
newMax.setMax(newMax, max);
newMin.setMin(newMin, min);
}
boundObjects(FALSE, newMin, newMax);
mBounds[0].setAdd(newMin, newMax);
mBounds[0].mul(0.5f);
mBounds[1].setSub(newMax, newMin);
mBounds[1].mul(0.5f);
}
clearState(DIRTY);
return;
}
//virtual
void LLviewerOctreeGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj)
{
obj->setGroup(this);
unbound();
setState(OBJECT_DIRTY);
}
//virtual
void LLviewerOctreeGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj)
{
obj->setGroup(NULL);
unbound();
setState(OBJECT_DIRTY);
}
//virtual
void LLviewerOctreeGroup::handleDestruction(const TreeNode* node)
{
for (OctreeNode::element_iter i = mOctreeNode->getDataBegin(); i != mOctreeNode->getDataEnd(); ++i)
{
LLViewerOctreeEntry* obj = *i;
if (obj && obj->getGroup() == this)
{
obj->nullGroup();
//obj->setGroup(NULL);
}
}
mOctreeNode = NULL;
}
//virtual
void LLviewerOctreeGroup::handleStateChange(const TreeNode* node)
{
//drop bounding box upon state change
if (mOctreeNode != node)
{
mOctreeNode = (OctreeNode*) node;
}
unbound();
}
//virtual
void LLviewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
{
if (child->getListenerCount() == 0)
{
new LLviewerOctreeGroup(child);
}
else
{
OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl;
}
unbound();
//((LLviewerOctreeGroup*)child->getListener(0))->unbound();
}
//virtual
void LLviewerOctreeGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child)
{
unbound();
}
LLviewerOctreeGroup* LLviewerOctreeGroup::getParent()
{
if(!mOctreeNode)
{
return NULL;
}
OctreeNode* parent = mOctreeNode->getOctParent();
if (parent)
{
return (LLviewerOctreeGroup*) parent->getListener(0);
}
return NULL;
}
//virtual
bool LLviewerOctreeGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut)
{
const OctreeNode* node = mOctreeNode;
if (node->isEmpty())
{ //don't do anything if there are no objects
if (empty && mOctreeNode->getParent())
{ //only root is allowed to be empty
OCT_ERRS << "Empty leaf found in octree." << llendl;
}
return false;
}
LLVector4a& newMin = mObjectExtents[0];
LLVector4a& newMax = mObjectExtents[1];
if (hasState(OBJECT_DIRTY))
{ //calculate new bounding box
clearState(OBJECT_DIRTY);
//initialize bounding box to first element
OctreeNode::const_element_iter i = node->getDataBegin();
LLViewerOctreeEntry* entry = *i;
const LLVector4a* minMax = entry->getSpatialExtents();
newMin = minMax[0];
newMax = minMax[1];
for (++i; i != node->getDataEnd(); ++i)
{
entry = *i;
minMax = entry->getSpatialExtents();
update_min_max(newMin, newMax, minMax[0]);
update_min_max(newMin, newMax, minMax[1]);
}
mObjectBounds[0].setAdd(newMin, newMax);
mObjectBounds[0].mul(0.5f);
mObjectBounds[1].setSub(newMax, newMin);
mObjectBounds[1].mul(0.5f);
}
if (empty)
{
minOut = newMin;
maxOut = newMax;
}
else
{
minOut.setMin(minOut, newMin);
maxOut.setMax(maxOut, newMax);
}
return TRUE;
}
//virtual
BOOL LLviewerOctreeGroup::isVisible() const
{
return mVisible[LLViewerCamera::sCurCameraID] >= LLViewerOctreeEntryData::getCurrentFrame() ? TRUE : FALSE;
}
//virtual
BOOL LLviewerOctreeGroup::isRecentlyVisible() const
{
return FALSE;
}
void LLviewerOctreeGroup::setVisible()
{
mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame();
}
//-----------------------------------------------------------------------------------
//class LLViewerOctreePartition definitions
//-----------------------------------------------------------------------------------
LLViewerOctreePartition::LLViewerOctreePartition() : mRegionp(NULL)
{
LLVector4a center, size;
center.splat(0.f);
size.splat(1.f);
mOctree = new OctreeRoot(center,size, NULL);
}
LLViewerOctreePartition::~LLViewerOctreePartition()
{
delete mOctree;
mOctree = NULL;
}
//-----------------------------------------------------------------------------------
//class LLViewerOctreeCull definitions
//-----------------------------------------------------------------------------------
//virtual
bool LLViewerOctreeCull::earlyFail(LLviewerOctreeGroup* group)
{
return false;
}
//virtual
void LLViewerOctreeCull::traverse(const OctreeNode* n)
{
LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) n->getListener(0);
if (earlyFail(group))
{
return;
}
if (mRes == 2 ||
(mRes && group->hasState(LLviewerOctreeGroup::SKIP_FRUSTUM_CHECK)))
{ //fully in, just add everything
OctreeTraveler::traverse(n);
}
else
{
mRes = frustumCheck(group);
if (mRes)
{ //at least partially in, run on down
OctreeTraveler::traverse(n);
}
mRes = 0;
}
}
//------------------------------------------
//agent space group culling
S32 LLViewerOctreeCull::AABBInFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
}
S32 LLViewerOctreeCull::AABBSphereIntersectGroupExtents(const LLviewerOctreeGroup* group)
{
return AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist);
}
S32 LLViewerOctreeCull::AABBInFrustumGroupBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]);
}
//------------------------------------------
//------------------------------------------
//agent space object set culling
S32 LLViewerOctreeCull::AABBInFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
}
S32 LLViewerOctreeCull::AABBSphereIntersectObjectExtents(const LLviewerOctreeGroup* group)
{
return AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist);
}
S32 LLViewerOctreeCull::AABBInFrustumObjectBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]);
}
//------------------------------------------
//------------------------------------------
//local regional space group culling
S32 LLViewerOctreeCull::AABBInRegionFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInRegionFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
}
S32 LLViewerOctreeCull::AABBInRegionFrustumGroupBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInRegionFrustum(group->mBounds[0], group->mBounds[1]);
}
S32 LLViewerOctreeCull::AABBRegionSphereIntersectGroupExtents(const LLviewerOctreeGroup* group, const LLVector3& shift)
{
return AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin() - shift, mCamera->mFrustumCornerDist);
}
//------------------------------------------
//------------------------------------------
//local regional space object culling
S32 LLViewerOctreeCull::AABBInRegionFrustumObjectBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInRegionFrustum(group->mObjectBounds[0], group->mObjectBounds[1]);
}
S32 LLViewerOctreeCull::AABBInRegionFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group)
{
return mCamera->AABBInRegionFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
}
S32 LLViewerOctreeCull::AABBRegionSphereIntersectObjectExtents(const LLviewerOctreeGroup* group, const LLVector3& shift)
{
return AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin() - shift, mCamera->mFrustumCornerDist);
}
//------------------------------------------
//virtual
bool LLViewerOctreeCull::checkObjects(const OctreeNode* branch, const LLviewerOctreeGroup* group)
{
if (branch->getElementCount() == 0) //no elements
{
return false;
}
else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box
{
return true;
}
else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum
{
return false;
}
return true;
}
//virtual
void LLViewerOctreeCull::preprocess(LLviewerOctreeGroup* group)
{
}
//virtual
void LLViewerOctreeCull::processGroup(LLviewerOctreeGroup* group)
{
}
//virtual
void LLViewerOctreeCull::visit(const OctreeNode* branch)
{
LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) branch->getListener(0);
preprocess(group);
if (checkObjects(branch, group))
{
processGroup(group);
}
}

View File

@ -0,0 +1,327 @@
/**
* @file llvieweroctree.h
* @brief LLViewerObjectOctree.cpp header file, defining all supporting classes.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_VIEWEROCTREE_H
#define LL_VIEWEROCTREE_H
#include <vector>
#include <map>
#include "v2math.h"
#include "v3math.h"
#include "v4math.h"
#include "m4math.h"
#include "llvector4a.h"
#include "llquaternion.h"
#include "lloctree.h"
#include "llviewercamera.h"
class LLViewerRegion;
class LLViewerOctreeEntryData;
class LLviewerOctreeGroup;
class LLViewerOctreeEntry;
typedef LLOctreeListener<LLViewerOctreeEntry> OctreeListener;
typedef LLTreeNode<LLViewerOctreeEntry> TreeNode;
typedef LLOctreeNode<LLViewerOctreeEntry> OctreeNode;
typedef LLOctreeRoot<LLViewerOctreeEntry> OctreeRoot;
typedef LLOctreeTraveler<LLViewerOctreeEntry> OctreeTraveler;
S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared);
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared);
//defines data needed for octree of an entry
LL_ALIGN_PREFIX(16)
class LLViewerOctreeEntry : public LLRefCount
{
friend class LLViewerOctreeEntryData;
public:
typedef enum
{
LLDRAWABLE = 0,
LLVOCACHEENTRY,
NUM_DATA_TYPE
}eEntryDataType_t;
~LLViewerOctreeEntry();
public:
LLViewerOctreeEntry();
void nullGroup(); //called by group handleDestruction() only
void setGroup(LLviewerOctreeGroup* group);
void removeData(LLViewerOctreeEntryData* data);
LLViewerOctreeEntryData* getData(U32 data_type)const {return mData[data_type];}
bool hasData(U32 data_type)const {return mData[data_type] != NULL;}
LLViewerOctreeEntryData* getDrawable() const {return mData[LLDRAWABLE];}
bool hasDrawable() const {return mData[LLDRAWABLE] != NULL;}
LLViewerOctreeEntryData* getVOCacheEntry() const {return mData[LLVOCACHEENTRY];}
bool hasVOCacheEntry() const {return mData[LLVOCACHEENTRY] != NULL;}
const LLVector4a* getSpatialExtents() const {return mExtents;}
const LLVector4a& getPositionGroup() const {return mPositionGroup;}
LLviewerOctreeGroup* getGroup()const {return mGroup;}
F32 getBinRadius() const {return mBinRadius;}
S32 getBinIndex() const {return mBinIndex; }
void setBinIndex(S32 index) const {mBinIndex = index; }
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}
private:
void addData(LLViewerOctreeEntryData* data);
private:
LLViewerOctreeEntryData* mData[NUM_DATA_TYPE]; //do not use LLPointer here.
LLviewerOctreeGroup* mGroup;
//aligned members
LL_ALIGN_16(LLVector4a mExtents[2]);
LL_ALIGN_16(LLVector4a mPositionGroup);
F32 mBinRadius;
mutable S32 mBinIndex;
mutable U32 mVisible;
} LL_ALIGN_POSTFIX(16);
//defines an abstract class for entry data
LL_ALIGN_PREFIX(16)
class LLViewerOctreeEntryData : public LLRefCount
{
protected:
~LLViewerOctreeEntryData();
public:
LLViewerOctreeEntryData(const LLViewerOctreeEntryData& rhs)
{
*this = rhs;
}
LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryDataType_t data_type);
LLViewerOctreeEntry::eEntryDataType_t getDataType() const {return mDataType;}
LLViewerOctreeEntry* getEntry() {return mEntry;}
virtual void setOctreeEntry(LLViewerOctreeEntry* entry);
virtual S32 getMinVisFrameRange()const = 0;
F32 getBinRadius() const {return mEntry->getBinRadius();}
const LLVector4a* getSpatialExtents() const;
LLviewerOctreeGroup* getGroup()const;
const LLVector4a& getPositionGroup() const;
void setBinRadius(F32 rad) {mEntry->mBinRadius = rad;}
void setSpatialExtents(const LLVector3& min, const LLVector3& max);
void setSpatialExtents(const LLVector4a& min, const LLVector4a& max);
void setPositionGroup(const LLVector4a& pos);
virtual void setGroup(LLviewerOctreeGroup* group);
void shift(const LLVector4a &shift_vector);
U32 getVisible() const {return mEntry ? mEntry->mVisible : 0;}
void setVisible() const;
virtual bool isVisible() const;
virtual bool isRecentlyVisible() const;
static S32 getCurrentFrame() { return sCurVisible; }
protected:
LLVector4a& getGroupPosition() {return mEntry->mPositionGroup;}
void initVisible(U32 visible) {mEntry->mVisible = visible;}
static void incrementVisible() {sCurVisible++;}
protected:
LLPointer<LLViewerOctreeEntry> mEntry;
LLViewerOctreeEntry::eEntryDataType_t mDataType;
static U32 sCurVisible; // Counter for what value of mVisible means currently visible
}LL_ALIGN_POSTFIX(16);
//defines an octree group for an octree node, which contains multiple entries.
LL_ALIGN_PREFIX(16)
class LLviewerOctreeGroup : public LLOctreeListener<LLViewerOctreeEntry>
{
friend class LLViewerOctreeCull;
protected:
~LLviewerOctreeGroup();
public:
enum
{
CLEAN = 0x00000000,
DIRTY = 0x00000001,
OBJECT_DIRTY = 0x00000002,
SKIP_FRUSTUM_CHECK = 0x00000004,
INVALID_STATE = 0x00000008,
};
public:
typedef LLOctreeNode<LLViewerOctreeEntry>::element_iter element_iter;
typedef LLOctreeNode<LLViewerOctreeEntry>::element_list element_list;
LLviewerOctreeGroup(OctreeNode* node);
LLviewerOctreeGroup(const LLviewerOctreeGroup& rhs)
{
*this = rhs;
}
void* operator new(size_t size)
{
return ll_aligned_malloc_16(size);
}
void operator delete(void* ptr)
{
ll_aligned_free_16(ptr);
}
bool removeFromGroup(LLViewerOctreeEntryData* data);
bool removeFromGroup(LLViewerOctreeEntry* entry);
virtual void unbound();
virtual void rebound();
void setVisible();
BOOL isVisible() const;
virtual BOOL isRecentlyVisible() const;
bool isEmpty() const { return mOctreeNode->isEmpty(); }
U32 getState() {return mState; }
bool isDirty() const {return mState & DIRTY;}
bool hasState(U32 state) const {return mState & state;}
void setState(U32 state) {mState |= state;}
void clearState(U32 state) {mState &= ~state;}
//LISTENER FUNCTIONS
virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj);
virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj);
virtual void handleDestruction(const TreeNode* node);
virtual void handleStateChange(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child);
OctreeNode* getOctreeNode() {return mOctreeNode;}
LLviewerOctreeGroup* getParent();
const LLVector4a* getBounds() const {return mBounds;}
const LLVector4a* getExtents() const {return mExtents;}
const LLVector4a* getObjectBounds() const {return mObjectBounds;}
const LLVector4a* getObjectExtents() const {return mObjectExtents;}
//octree wrappers to make code more readable
element_list& getData() { return mOctreeNode->getData(); }
element_iter getDataBegin() { return mOctreeNode->getDataBegin(); }
element_iter getDataEnd() { return mOctreeNode->getDataEnd(); }
U32 getElementCount() const { return mOctreeNode->getElementCount(); }
bool hasElement(LLViewerOctreeEntryData* data);
private:
virtual bool boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut);
protected:
U32 mState;
OctreeNode* mOctreeNode;
LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects)
LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node
LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children
LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node
public:
S32 mVisible[LLViewerCamera::NUM_CAMERAS];
}LL_ALIGN_POSTFIX(16);
class LLViewerOctreePartition
{
public:
LLViewerOctreePartition();
virtual ~LLViewerOctreePartition();
// Cull on arbitrary frustum
virtual S32 cull(LLCamera &camera) = 0;
public:
U32 mPartitionType;
OctreeNode* mOctree;
LLViewerRegion* mRegionp; // the region this partition belongs to.
};
class LLViewerOctreeCull : public OctreeTraveler
{
public:
LLViewerOctreeCull(LLCamera* camera)
: mCamera(camera), mRes(0) { }
virtual bool earlyFail(LLviewerOctreeGroup* group);
virtual void traverse(const OctreeNode* n);
//agent space group cull
S32 AABBInFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group);
S32 AABBSphereIntersectGroupExtents(const LLviewerOctreeGroup* group);
S32 AABBInFrustumGroupBounds(const LLviewerOctreeGroup* group);
//agent space object set cull
S32 AABBInFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group);
S32 AABBSphereIntersectObjectExtents(const LLviewerOctreeGroup* group);
S32 AABBInFrustumObjectBounds(const LLviewerOctreeGroup* group);
//local region space group cull
S32 AABBInRegionFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group);
S32 AABBInRegionFrustumGroupBounds(const LLviewerOctreeGroup* group);
S32 AABBRegionSphereIntersectGroupExtents(const LLviewerOctreeGroup* group, const LLVector3& shift);
//local region space object set cull
S32 AABBInRegionFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group);
S32 AABBInRegionFrustumObjectBounds(const LLviewerOctreeGroup* group);
S32 AABBRegionSphereIntersectObjectExtents(const LLviewerOctreeGroup* group, const LLVector3& shift);
virtual S32 frustumCheck(const LLviewerOctreeGroup* group) = 0;
virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) = 0;
virtual bool checkObjects(const OctreeNode* branch, const LLviewerOctreeGroup* group);
virtual void preprocess(LLviewerOctreeGroup* group);
virtual void processGroup(LLviewerOctreeGroup* group);
virtual void visit(const OctreeNode* branch);
protected:
LLCamera *mCamera;
S32 mRes;
};
#endif

View File

@ -151,8 +151,8 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 bo
if (group != NULL)
{
LLVector3 center(group->mOctreeNode->getCenter().getF32ptr());
LLVector3 size(group->mOctreeNode->getSize().getF32ptr());
LLVector3 center(group->getOctreeNode()->getCenter().getF32ptr());
LLVector3 size(group->getOctreeNode()->getSize().getF32ptr());
size += LLVector3(0.01f, 0.01f, 0.01f);
mMinObjPos = center - size;
mMaxObjPos = center + size;

View File

@ -70,6 +70,7 @@
#include "stringize.h"
#include "llviewercontrol.h"
#include "llsdserialize.h"
#include "llvieweroctree.h"
#ifdef LL_WINDOWS
#pragma warning(disable:4355)
@ -85,6 +86,9 @@ const F32 CAP_REQUEST_TIMEOUT = 18;
// Even though we gave up on login, keep trying for caps after we are logged in:
const S32 MAX_CAP_REQUEST_ATTEMPTS = 30;
LLViewerRegion* LLViewerRegion::sCurRegionp = NULL;
BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE;
typedef std::map<std::string, std::string> CapabilityMap;
class LLViewerRegionImpl {
@ -97,6 +101,8 @@ public:
mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN),
mSeedCapAttempts(0),
mHttpResponderID(0),
mLastCameraUpdate(0),
mLastCameraOrigin(),
// I'd prefer to set the LLCapabilityListener name to match the region
// name -- it's disappointing that's not available at construction time.
// We could instead store an LLCapabilityListener*, making
@ -133,7 +139,14 @@ public:
// Misc
LLVLComposition *mCompositionp; // Composition layer for the surface
LLVOCacheEntry::vocache_entry_map_t mCacheMap;
LLVOCacheEntry::vocache_entry_map_t mCacheMap; //all cached entries
LLVOCacheEntry::vocache_entry_set_t mActiveSet; //all active entries;
LLVOCacheEntry::vocache_entry_set_t mWaitingSet; //entries waiting for LLDrawable to be generated.
std::set< LLviewerOctreeGroup* > mVisibleGroups; //visible groupa
LLVOCachePartition* mVOCachePartition;
LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation.
LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation.
// time?
// LRU info?
@ -157,7 +170,10 @@ public:
LLCapabilityListener mCapabilityListener;
//spatial partitions for objects in this region
std::vector<LLSpatialPartition*> mObjectPartition;
std::vector<LLViewerOctreePartition*> mObjectPartition;
LLVector3 mLastCameraOrigin;
U32 mLastCameraUpdate;
};
// support for secondlife:///app/region/{REGION} SLapps
@ -292,7 +308,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
mReleaseNotesRequested(FALSE),
mCapabilitiesReceived(false),
mBitsReceived(0.f),
mPacketsReceived(0.f)
mPacketsReceived(0.f),
mDead(FALSE)
{
mWidth = region_width_meters;
mImpl->mOriginGlobal = from_region_handle(handle);
@ -324,17 +341,20 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
//create object partitions
//MUST MATCH declaration of eObjectPartitions
mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD
mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN
mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER
mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER
mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE
mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE
mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS
mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME
mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE
mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE
mImpl->mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD
mImpl->mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN
mImpl->mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER
mImpl->mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER
mImpl->mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE
mImpl->mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE
mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS
mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME
mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE
mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE
mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE
mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE
mImpl->mVOCachePartition = getVOCachePartition();
}
@ -355,6 +375,12 @@ void LLViewerRegion::initStats()
LLViewerRegion::~LLViewerRegion()
{
mDead = TRUE;
mImpl->mActiveSet.clear();
mImpl->mVisibleEntries.clear();
mImpl->mVisibleGroups.clear();
mImpl->mWaitingSet.clear();
gVLManager.cleanupData(this);
// Can't do this on destruction, because the neighbor pointers might be invalid.
// This should be reference counted...
@ -367,12 +393,12 @@ LLViewerRegion::~LLViewerRegion()
delete mParcelOverlay;
delete mImpl->mLandp;
delete mImpl->mEventPoll;
LLHTTPSender::clearSender(mImpl->mHost);
saveObjectCache();
LLHTTPSender::clearSender(mImpl->mHost);
std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
saveObjectCache();
delete mImpl;
mImpl = NULL;
}
@ -438,10 +464,6 @@ void LLViewerRegion::saveObjectCache()
mCacheDirty = FALSE;
}
for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter)
{
delete iter->second;
}
mImpl->mCacheMap.clear();
}
@ -719,8 +741,354 @@ void LLViewerRegion::dirtyHeights()
}
}
void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry)
{
U32 state = LLVOCacheEntry::INACTIVE;
if(old_entry)
{
old_entry->copyTo(new_entry);
state = old_entry->getState();
killCacheEntry(old_entry);
}
mImpl->mCacheMap[new_entry->getLocalID()] = new_entry;
if(state == LLVOCacheEntry::ACTIVE)
{
llassert(new_entry->getEntry()->hasDrawable());
mImpl->mActiveSet.insert(new_entry);
}
else if(state == LLVOCacheEntry::WAITING)
{
mImpl->mWaitingSet.insert(new_entry);
}
else if(old_entry && new_entry->getEntry())
{
addToVOCacheTree(new_entry);
}
new_entry->setState(state);
}
//physically delete the cache entry
void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry)
{
if(!entry)
{
return;
}
//remove from active list and waiting list
if(entry->isState(LLVOCacheEntry::ACTIVE))
{
mImpl->mActiveSet.erase(entry);
}
else
{
if(entry->isState(LLVOCacheEntry::WAITING))
{
mImpl->mWaitingSet.erase(entry);
}
//remove from mVOCachePartition
removeFromVOCacheTree(entry);
}
//remove from the forced visible list
mImpl->mVisibleEntries.erase(entry);
//kill LLViewerObject if exists
//this should be done by the rendering pipeline automatically.
entry->setState(LLVOCacheEntry::INACTIVE);
//remove from mCacheMap, real deletion
mImpl->mCacheMap.erase(entry->getLocalID());
}
//physically delete the cache entry
void LLViewerRegion::killCacheEntry(U32 local_id)
{
killCacheEntry(getCacheEntry(local_id));
}
U32 LLViewerRegion::getNumOfActiveCachedObjects() const
{
return mImpl->mActiveSet.size();
}
void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry)
{
if(!entry || mDead)
{
return;
}
if(entry->isState(LLVOCacheEntry::WAITING))
{
mImpl->mWaitingSet.erase(entry);
}
entry->setState(LLVOCacheEntry::ACTIVE);
entry->setVisible();
llassert(entry->getEntry()->hasDrawable());
mImpl->mActiveSet.insert(entry);
}
void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep)
{
if(mDead)
{
return;
}
if(drawablep->getParent()) //child object
{
LLViewerOctreeEntry* parent_oct_entry = drawablep->getParent()->getEntry();
if(parent_oct_entry && parent_oct_entry->hasVOCacheEntry())
{
LLVOCacheEntry* parent = (LLVOCacheEntry*)parent_oct_entry->getVOCacheEntry();
parent->addChild(entry);
}
}
else //insert to vo cache tree.
{
//shift to the local regional space from agent space
const LLVector3 pos = drawablep->getVObj()->getPositionRegion();
LLVector4a vec(pos[0], pos[1], pos[2]);
LLVector4a shift;
shift.setSub(vec, entry->getPositionGroup());
entry->shift(shift);
addToVOCacheTree(entry);
}
mImpl->mVisibleEntries.erase(entry);
mImpl->mActiveSet.erase(entry);
mImpl->mWaitingSet.erase(entry);
entry->setState(LLVOCacheEntry::INACTIVE);
}
void LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group)
{
if(mDead || group->isEmpty())
{
return;
}
group->setVisible();
mImpl->mVisibleGroups.insert(group);
}
void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
{
if(!sVOCacheCullingEnabled)
{
return;
}
if(mDead || !entry || !entry->getEntry())
{
return;
}
if(entry->getGroup()) //already in octree.
{
return;
}
if(!entry->hasState(LLVOCacheEntry::ADD_TO_CACHE_TREE))
{
return; //can not add to vo cache tree.
}
mImpl->mVOCachePartition->addEntry(entry->getEntry());
}
void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry)
{
if(mDead || !entry || !entry->getEntry())
{
return;
}
if(!entry->getGroup())
{
return;
}
mImpl->mVOCachePartition->removeEntry(entry->getEntry());
}
//add the visible entries
void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry)
{
if(mDead || !entry)
{
return;
}
if(entry->isState(LLVOCacheEntry::IN_QUEUE))
{
return;
}
if(entry->isState(LLVOCacheEntry::INACTIVE))
{
entry->setState(LLVOCacheEntry::IN_QUEUE);
}
mImpl->mVisibleEntries.insert(entry);
}
void LLViewerRegion::clearVisibleGroup(LLviewerOctreeGroup* group)
{
if(mDead)
{
return;
}
llassert(!group->getOctreeNode() || group->isEmpty());
mImpl->mVisibleGroups.erase(group);
}
F32 LLViewerRegion::updateVisibleEntries(F32 max_time)
{
if(mImpl->mVisibleGroups.empty() && mImpl->mVisibleEntries.empty())
{
return max_time;
}
LLTimer update_timer;
const LLVector3 camera_origin = LLViewerCamera::getInstance()->getOrigin();
const U32 cur_frame = LLViewerOctreeEntryData::getCurrentFrame();
bool needs_update = ((cur_frame - mImpl->mLastCameraUpdate) > 5) && ((camera_origin - mImpl->mLastCameraOrigin).lengthSquared() > 10.f);
//process visible entries
max_time *= 0.5f; //only use up to half available time to update entries.
#if 1
for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();)
{
LLVOCacheEntry* vo_entry = *iter;
vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate);
if(vo_entry->getState() < LLVOCacheEntry::WAITING)
{
mImpl->mWaitingList.insert(vo_entry);
}
LLVOCacheEntry* child;
S32 num_child = vo_entry->getNumOfChildren();
S32 num_done = 0;
for(S32 i = 0; i < num_child; i++)
{
child = vo_entry->getChild(i);
if(child->getState() < LLVOCacheEntry::WAITING)
{
child->setSceneContribution(vo_entry->getSceneContribution());
mImpl->mWaitingList.insert(child);
}
else
{
num_done++;
}
}
if(num_done == num_child)
{
vo_entry->clearChildrenList();
}
if(!vo_entry->getNumOfChildren())
{
if(vo_entry->getState() >= LLVOCacheEntry::WAITING)
{
iter = mImpl->mVisibleEntries.erase(iter);
}
else
{
++iter;
}
}
else
{
++iter;
}
//if(update_timer.getElapsedTimeF32() > max_time)
//{
// break;
//}
}
#endif
//process visible groups
std::set< LLviewerOctreeGroup* >::iterator group_iter = mImpl->mVisibleGroups.begin();
for(; group_iter != mImpl->mVisibleGroups.end(); ++group_iter)
{
LLviewerOctreeGroup* group = *group_iter;
if(!group->getOctreeNode() || group->isEmpty())
{
continue;
}
for (LLviewerOctreeGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
if((*i)->hasVOCacheEntry())
{
LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry();
vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate);
mImpl->mWaitingList.insert(vo_entry);
}
}
//if(update_timer.getElapsedTimeF32() > max_time)
//{
// break;
//}
}
mImpl->mVisibleGroups.clear();
if(needs_update)
{
mImpl->mLastCameraOrigin = camera_origin;
mImpl->mLastCameraUpdate = cur_frame;
}
return 2.0f * max_time - update_timer.getElapsedTimeF32();
}
F32 LLViewerRegion::createVisibleObjects(F32 max_time)
{
if(mImpl->mWaitingList.empty())
{
return max_time;
}
LLTimer update_timer;
S32 max_num_objects = 64; //minimum number of new objects to be added
for(LLVOCacheEntry::vocache_entry_priority_list_t::iterator iter = mImpl->mWaitingList.begin();
iter != mImpl->mWaitingList.end(); ++iter)
{
LLVOCacheEntry* vo_entry = *iter;
if(vo_entry->getState() < LLVOCacheEntry::WAITING)
{
addNewObject(vo_entry);
if(max_num_objects-- < 0 && update_timer.getElapsedTimeF32() > max_time)
{
break;
}
}
}
mImpl->mWaitingList.clear();
return max_time - update_timer.getElapsedTimeF32();
}
BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
{
LLTimer update_timer;
// did_update returns TRUE if we did at least one significant update
BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time);
@ -730,9 +1098,98 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time)
mParcelOverlay->idleUpdate();
}
max_update_time -= update_timer.getElapsedTimeF32();
if(max_update_time < 0.f || mImpl->mCacheMap.empty())
{
return did_update;
}
sCurRegionp = this;
//kill invisible objects
max_update_time = killInvisibleObjects(max_update_time);
max_update_time = updateVisibleEntries(max_update_time);
createVisibleObjects(max_update_time);
mImpl->mVisibleGroups.clear();
mImpl->mWaitingList.clear();
sCurRegionp = NULL;
return did_update;
}
F32 LLViewerRegion::killInvisibleObjects(F32 max_time)
{
if(!sVOCacheCullingEnabled)
{
return max_time;
}
std::vector<LLDrawable*> delete_list;
for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.begin();
iter != mImpl->mActiveSet.end(); ++iter)
{
if(!(*iter)->isRecentlyVisible())
{
killObject((*iter), delete_list);
}
}
for(S32 i = 0; i < delete_list.size(); i++)
{
gObjectList.killObject(delete_list[i]->getVObj(), true);
}
delete_list.clear();
return max_time;
}
void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list)
{
//kill the object.
LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable();
llassert(drawablep);
if(!drawablep->getParent())
{
LLViewerObject::const_child_list_t& child_list = drawablep->getVObj()->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); iter++)
{
LLViewerObject* child = *iter;
if(child->mDrawable->isRecentlyVisible())
{
//set the parent group visible if any of its children visible.
((LLViewerOctreeEntryData*)drawablep)->setVisible();
return;
}
}
delete_list.push_back(drawablep);
}
}
LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry)
{
LLViewerObject* obj = NULL;
if(!entry->getEntry()->hasDrawable()) //not added to the rendering pipeline yet
{
//add the object
obj = gObjectList.processObjectUpdateFromCache(entry, this);
if(obj)
{
if(!entry->isState(LLVOCacheEntry::ACTIVE))
{
mImpl->mWaitingSet.insert(entry);
entry->setState(LLVOCacheEntry::WAITING);
}
}
}
else
{
llerrs << "Object is already created." << llendl;
}
return obj;
}
// As above, but forcibly do the update.
void LLViewerRegion::forceUpdate()
@ -1191,8 +1648,9 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
{
U32 local_id = objectp->getLocalID();
U32 crc = objectp->getCRC();
eCacheUpdateResult result;
LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
LLVOCacheEntry* entry = getCacheEntry(local_id);
if (entry)
{
@ -1201,41 +1659,72 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
{
// Record a hit
entry->recordDupe();
return CACHE_UPDATE_DUPE;
result = CACHE_UPDATE_DUPE;
}
else
{
// Update the cache entry
LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp);
replaceCacheEntry(entry, new_entry);
entry = new_entry;
// Update the cache entry
mImpl->mCacheMap.erase(local_id);
delete entry;
entry = new LLVOCacheEntry(local_id, crc, dp);
mImpl->mCacheMap[local_id] = entry;
return CACHE_UPDATE_CHANGED;
result = CACHE_UPDATE_CHANGED;
}
}
// we haven't seen this object before
// Create new entry and add to map
eCacheUpdateResult result = CACHE_UPDATE_ADDED;
if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
else
{
delete mImpl->mCacheMap.begin()->second ;
mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
result = CACHE_UPDATE_REPLACED;
}
entry = new LLVOCacheEntry(local_id, crc, dp);
// we haven't seen this object before
// Create new entry and add to map
result = CACHE_UPDATE_ADDED;
//if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES)
//{
// delete mImpl->mCacheMap.begin()->second ;
// mImpl->mCacheMap.erase(mImpl->mCacheMap.begin());
// result = CACHE_UPDATE_REPLACED;
//
//}
entry = new LLVOCacheEntry(local_id, crc, dp);
mImpl->mCacheMap[local_id] = entry;
}
if(objectp->mDrawable.notNull() && !entry->getEntry())
{
entry->setOctreeEntry(objectp->mDrawable->getEntry());
}
if(entry->getEntry() && entry->getEntry()->hasDrawable() && entry->isState(LLVOCacheEntry::INACTIVE))
{
addActiveCacheEntry(entry);
}
mImpl->mCacheMap[local_id] = entry;
return result;
}
LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
{
LLVOCacheEntry* entry = getCacheEntry(local_id);
removeFromVOCacheTree(entry);
return entry;
}
LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id)
{
LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id);
if(iter != mImpl->mCacheMap.end())
{
return iter->second;
}
return NULL;
}
// Get data packer for this object, if we have cached data
// AND the CRC matches. JC
LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U8 &cache_miss_type)
{
//llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18
LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL);
LLVOCacheEntry* entry = getCacheEntry(local_id);
if (entry)
{
@ -1244,24 +1733,31 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type)
{
// Record a hit
entry->recordHit();
cache_miss_type = CACHE_MISS_TYPE_NONE;
return entry->getDP(crc);
cache_miss_type = CACHE_MISS_TYPE_NONE;
if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE))
{
return true;
}
addVisibleCacheEntry(entry);
return true;
}
else
{
// llinfos << "CRC miss for " << local_id << llendl;
cache_miss_type = CACHE_MISS_TYPE_CRC;
cache_miss_type = CACHE_MISS_TYPE_CRC;
mCacheMissCRC.put(local_id);
}
}
else
{
// llinfos << "Cache miss for " << local_id << llendl;
cache_miss_type = CACHE_MISS_TYPE_FULL;
cache_miss_type = CACHE_MISS_TYPE_FULL;
mCacheMissFull.put(local_id);
}
return NULL;
return false;
}
void LLViewerRegion::addCacheMissFull(const U32 local_id)
@ -1784,9 +2280,18 @@ void LLViewerRegion::logActiveCapabilities() const
LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type)
{
if (type < mImpl->mObjectPartition.size())
if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE)
{
return mImpl->mObjectPartition[type];
return (LLSpatialPartition*)mImpl->mObjectPartition[type];
}
return NULL;
}
LLVOCachePartition* LLViewerRegion::getVOCachePartition()
{
if(PARTITION_VO_CACHE < mImpl->mObjectPartition.size())
{
return (LLVOCachePartition*)mImpl->mObjectPartition[PARTITION_VO_CACHE];
}
return NULL;
}

View File

@ -65,8 +65,11 @@ class LLDataPacker;
class LLDataPackerBinaryBuffer;
class LLHost;
class LLBBox;
class LLSpatialGroup;
class LLDrawable;
class LLViewerRegionImpl;
class LLviewerOctreeGroup;
class LLVOCachePartition;
class LLViewerRegion: public LLCapabilityProvider // implements this interface
{
@ -83,7 +86,8 @@ public:
PARTITION_GRASS,
PARTITION_VOLUME,
PARTITION_BRIDGE,
PARTITION_HUD_PARTICLE,
PARTITION_HUD_PARTICLE,
PARTITION_VO_CACHE,
PARTITION_NONE,
NUM_PARTITIONS
} eObjectPartitions;
@ -215,6 +219,12 @@ public:
F32 getWidth() const { return mWidth; }
BOOL idleUpdate(F32 max_update_time);
void addVisibleGroup(LLviewerOctreeGroup* group);
void addVisibleCacheEntry(LLVOCacheEntry* entry);
void addActiveCacheEntry(LLVOCacheEntry* entry);
void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep);
void killCacheEntry(U32 local_id); //physically delete the cache entry
void clearVisibleGroup(LLviewerOctreeGroup* group);
// Like idleUpdate, but forces everything to complete regardless of
// how long it takes.
@ -304,8 +314,9 @@ public:
} eCacheUpdateResult;
// handle a full update message
eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type);
eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp);
LLVOCacheEntry* getCacheEntryForOctree(U32 local_id);
bool probeCache(U32 local_id, U32 crc, U8 &cache_miss_type);
void requestCacheMisses();
void addCacheMissFull(const U32 local_id);
@ -321,7 +332,9 @@ public:
virtual std::string getDescription() const;
std::string getHttpUrl() const { return mHttpUrl ;}
U32 getNumOfActiveCachedObjects() const;
LLSpatialPartition* getSpatialPartition(U32 type);
LLVOCachePartition* getVOCachePartition();
bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
bool childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const;
@ -330,6 +343,19 @@ public:
void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions );
void getNeighboringRegionsStatus( std::vector<S32>& regions );
private:
void addToVOCacheTree(LLVOCacheEntry* entry);
LLViewerObject* addNewObject(LLVOCacheEntry* entry);
void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list);
LLVOCacheEntry* getCacheEntry(U32 local_id);
void removeFromVOCacheTree(LLVOCacheEntry* entry);
void replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry);
void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry
F32 killInvisibleObjects(F32 max_time);
F32 createVisibleObjects(F32 max_time);
F32 updateVisibleEntries(F32 max_time); //update visible entries
public:
struct CompareDistance
{
@ -363,6 +389,8 @@ public:
LLDynamicArray<U32> mMapAvatars;
LLDynamicArray<LLUUID> mMapAvatarIDs;
static LLViewerRegion* sCurRegionp;
static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not.
private:
LLViewerRegionImpl * mImpl;
@ -406,18 +434,17 @@ private:
// Maps local ids to cache entries.
// Regions can have order 10,000 objects, so assume
// a structure of size 2^14 = 16,000
BOOL mCacheLoaded;
BOOL mCacheDirty;
BOOL mCacheLoaded;
BOOL mCacheDirty;
BOOL mAlive; // can become false if circuit disconnects
BOOL mCapabilitiesReceived;
BOOL mReleaseNotesRequested;
BOOL mDead; //if true, this region is in the process of deleting.
LLDynamicArray<U32> mCacheMissFull;
LLDynamicArray<U32> mCacheMissCRC;
bool mAlive; // can become false if circuit disconnects
bool mCapabilitiesReceived;
caps_received_signal_t mCapabilitiesReceivedSignal;
BOOL mReleaseNotesRequested;
caps_received_signal_t mCapabilitiesReceivedSignal;
LLSD mSimulatorFeatures;
};

View File

@ -78,6 +78,8 @@ LLGLSLShader gGlowCombineProgram;
LLGLSLShader gSplatTextureRectProgram;
LLGLSLShader gGlowCombineFXAAProgram;
LLGLSLShader gTwoTextureAddProgram;
LLGLSLShader gTwoTextureCompareProgram;
LLGLSLShader gOneTextureFilterProgram;
LLGLSLShader gOneTextureNoColorProgram;
LLGLSLShader gDebugProgram;
LLGLSLShader gClipProgram;
@ -672,6 +674,8 @@ void LLViewerShaderMgr::unloadShaders()
gSplatTextureRectProgram.unload();
gGlowCombineFXAAProgram.unload();
gTwoTextureAddProgram.unload();
gTwoTextureCompareProgram.unload();
gOneTextureFilterProgram.unload();
gOneTextureNoColorProgram.unload();
gSolidColorProgram.unload();
@ -2706,6 +2710,37 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
}
}
if (success)
{
gTwoTextureCompareProgram.mName = "Two Texture Compare Shader";
gTwoTextureCompareProgram.mShaderFiles.clear();
gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB));
gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB));
gTwoTextureCompareProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
success = gTwoTextureCompareProgram.createShader(NULL, NULL);
if (success)
{
gTwoTextureCompareProgram.bind();
gTwoTextureCompareProgram.uniform1i("tex0", 0);
gTwoTextureCompareProgram.uniform1i("tex1", 1);
}
}
if (success)
{
gOneTextureFilterProgram.mName = "One Texture Filter Shader";
gOneTextureFilterProgram.mShaderFiles.clear();
gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB));
gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB));
gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
success = gOneTextureFilterProgram.createShader(NULL, NULL);
if (success)
{
gOneTextureFilterProgram.bind();
gOneTextureFilterProgram.uniform1i("tex0", 0);
}
}
if (success)
{
gOneTextureNoColorProgram.mName = "One Texture No Color Shader";

View File

@ -233,7 +233,11 @@ extern LLGLSLShader gAlphaMaskProgram;
//output tex0[tc0] + tex1[tc1]
extern LLGLSLShader gTwoTextureAddProgram;
//output tex0[tc0] - tex1[tc1]
extern LLGLSLShader gTwoTextureCompareProgram;
//discard some fragments based on user-set color tolerance
extern LLGLSLShader gOneTextureFilterProgram;
extern LLGLSLShader gOneTextureNoColorProgram;
//object shaders

View File

@ -220,7 +220,7 @@ void LLViewerStatsRecorder::writeToLog( F32 interval )
}
else
{
llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl;
//llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl;
return;
}
}

View File

@ -966,6 +966,12 @@ void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
//nothing here.
}
BOOL LLViewerTexture::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->setSubImageFromFrameBuffer(fb_x, fb_y, x_pos, y_pos, width, height);
}
void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
{
llassert(mGLTexturep.notNull()) ;

View File

@ -212,6 +212,7 @@ public:
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLViewerTexture::OTHER);
virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
void setAddressMode(LLTexUnit::eTextureAddressMode mode);

View File

@ -102,6 +102,7 @@
#include "lldebugmessagebox.h"
#include "llsdutil.h"
#include "llscenemonitor.h"
extern F32 SPEED_ADJUST_MAX;
extern F32 SPEED_ADJUST_MAX_SEC;
@ -771,6 +772,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mLastPelvisToFoot = 0.0f;
mPelvisFixup = 0.0f;
mLastPelvisFixup = 0.0f;
if(LLSceneMonitor::getInstance()->isEnabled())
{
LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this);
}
}
std::string LLVOAvatar::avString() const

View File

@ -808,8 +808,10 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys,
updateMeshTextures();
// unpack the texture UUIDs to the texture slots
retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
if(mesgsys != NULL)
{
retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
}
// need to trigger a few operations to get the avatar to use the new bakes
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{

View File

@ -29,6 +29,10 @@
#include "llerror.h"
#include "llregionhandle.h"
#include "llviewercontrol.h"
#include "llviewerobjectlist.h"
#include "lldrawable.h"
#include "llviewerregion.h"
#include "pipeline.h"
BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes)
{
@ -46,12 +50,16 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
//---------------------------------------------------------------------------
LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp)
:
: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
mLocalID(local_id),
mCRC(crc),
mHitCount(0),
mDupeCount(0),
mCRCChangeCount(0)
mCRCChangeCount(0),
mState(INACTIVE),
mRepeatedVisCounter(0),
mVisFrameRange(64),
mSceneContrib(0.f)
{
mBuffer = new U8[dp.getBufferSize()];
mDP.assignBuffer(mBuffer, dp.getBufferSize());
@ -59,24 +67,35 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &
}
LLVOCacheEntry::LLVOCacheEntry()
:
: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
mLocalID(0),
mCRC(0),
mHitCount(0),
mDupeCount(0),
mCRCChangeCount(0),
mBuffer(NULL)
mBuffer(NULL),
mState(INACTIVE),
mRepeatedVisCounter(0),
mVisFrameRange(64),
mSceneContrib(0.f)
{
mDP.assignBuffer(mBuffer, 0);
}
LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
: mBuffer(NULL)
: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
mBuffer(NULL),
mState(INACTIVE),
mRepeatedVisCounter(0),
mVisFrameRange(64),
mSceneContrib(0.f)
{
S32 size = -1;
BOOL success;
mDP.assignBuffer(mBuffer, 0);
setOctreeEntry(NULL);
success = check_read(apr_file, &mLocalID, sizeof(U32));
if(success)
{
@ -95,6 +114,36 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
success = check_read(apr_file, &mCRCChangeCount, sizeof(S32));
}
if(success)
{
success = check_read(apr_file, &mState, sizeof(U32));
}
if(success)
{
F32 ext[8];
success = check_read(apr_file, (void*)ext, sizeof(F32) * 8);
LLVector4a exts[2];
exts[0].load4a(ext);
exts[1].load4a(&ext[4]);
setSpatialExtents(exts[0], exts[1]);
}
if(success)
{
LLVector4 pos;
success = check_read(apr_file, (void*)pos.mV, sizeof(LLVector4));
LLVector4a pos_;
pos_.load4a(pos.mV);
setPositionGroup(pos_);
}
if(success)
{
F32 rad;
success = check_read(apr_file, &rad, sizeof(F32));
setBinRadius(rad);
}
if(success)
{
success = check_read(apr_file, &size, sizeof(S32));
@ -132,32 +181,100 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
mDupeCount = 0;
mCRCChangeCount = 0;
mBuffer = NULL;
mEntry = NULL;
mState = 0;
}
}
LLVOCacheEntry::~LLVOCacheEntry()
{
mDP.freeBuffer();
//llassert(mState == INACTIVE);
}
// New CRC means the object has changed.
void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp)
//virtual
void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry)
{
if ( (mCRC != crc)
||(mDP.getBufferSize() == 0))
if(!entry && mDP.getBufferSize() > 0)
{
mCRC = crc;
mHitCount = 0;
mCRCChangeCount++;
LLUUID fullid;
mDP.reset();
mDP.unpackUUID(fullid, "ID");
mDP.reset();
mDP.freeBuffer();
mBuffer = new U8[dp.getBufferSize()];
mDP.assignBuffer(mBuffer, dp.getBufferSize());
mDP = dp;
LLViewerObject* obj = gObjectList.findObject(fullid);
if(obj && obj->mDrawable)
{
entry = obj->mDrawable->getEntry();
}
}
LLViewerOctreeEntryData::setOctreeEntry(entry);
}
void LLVOCacheEntry::copyTo(LLVOCacheEntry* new_entry)
{
//copy LLViewerOctreeEntry
if(mEntry.notNull())
{
new_entry->setOctreeEntry(mEntry);
mEntry = NULL;
}
//copy children
S32 num_children = getNumOfChildren();
for(S32 i = 0; i < num_children; i++)
{
new_entry->addChild(getChild(i));
}
}
void LLVOCacheEntry::setState(U32 state)
{
mState &= 0xffff0000; //clear the low 16 bits
state &= 0x0000ffff; //clear the high 16 bits;
mState |= state;
if(getState() == ACTIVE)
{
const S32 MIN_REAVTIVE_INTERVAL = 20;
U32 last_visible = getVisible();
setVisible();
if(getVisible() - last_visible < MIN_REAVTIVE_INTERVAL + mVisFrameRange)
{
mRepeatedVisCounter++;
}
else
{
mRepeatedVisCounter = 0;
mVisFrameRange = 64;
}
if(mRepeatedVisCounter > 2)
{
//if repeatedly becomes visible immediately after invisible, enlarge the visible frame range
mRepeatedVisCounter = 0;
mVisFrameRange *= 2;
}
}
}
//virtual
S32 LLVOCacheEntry::getMinVisFrameRange()const
{
return mVisFrameRange;
}
void LLVOCacheEntry::addChild(LLVOCacheEntry* entry)
{
llassert(entry != NULL);
mChildrenList.push_back(entry);
}
LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc)
{
if ( (mCRC != crc)
@ -170,6 +287,16 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc)
return &mDP;
}
LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP()
{
if (mDP.getBufferSize() == 0)
{
//llinfos << "Not getting cache entry, invalid!" << llendl;
return NULL;
}
return &mDP;
}
void LLVOCacheEntry::recordHit()
{
@ -189,6 +316,11 @@ void LLVOCacheEntry::dump() const
BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
{
if(!mEntry)
{
return FALSE;
}
BOOL success;
success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
if(success)
@ -208,6 +340,33 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
}
if(success)
{
U32 state = mState & 0xffff0000; //only store the high 16 bits.
success = check_write(apr_file, (void*)&state, sizeof(U32));
}
if(success)
{
const LLVector4a* exts = getSpatialExtents() ;
LLVector4 ext(exts[0][0], exts[0][1], exts[0][2], exts[0][3]);
success = check_write(apr_file, ext.mV, sizeof(LLVector4));
if(success)
{
ext.set(exts[1][0], exts[1][1], exts[1][2], exts[1][3]);
success = check_write(apr_file, ext.mV, sizeof(LLVector4));
}
}
if(success)
{
const LLVector4a pos_ = getPositionGroup() ;
LLVector4 pos(pos_[0], pos_[1], pos_[2], pos_[3]);
success = check_write(apr_file, pos.mV, sizeof(LLVector4));
}
if(success)
{
F32 rad = getBinRadius();
success = check_write(apr_file, (void*)&rad, sizeof(F32));
}
if(success)
{
S32 size = mDP.getBufferSize();
success = check_write(apr_file, (void*)&size, sizeof(S32));
@ -221,6 +380,121 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
return success ;
}
void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update)
{
if(!needs_update && getVisible() >= last_update)
{
return; //no need to update
}
const LLVector4a& center = getPositionGroup();
LLVector4a origin;
origin.load3(camera_origin.mV);
LLVector4a lookAt;
lookAt.setSub(center, origin);
F32 squared_dist = lookAt.dot3(lookAt).getF32();
F32 rad = getBinRadius();
mSceneContrib = rad * rad / squared_dist;
setVisible();
}
//-------------------------------------------------------------------
//LLVOCachePartition
//-------------------------------------------------------------------
LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp)
{
mRegionp = regionp;
mPartitionType = LLViewerRegion::PARTITION_VO_CACHE;
mVisitedTime = 0;
new LLviewerOctreeGroup(mOctree);
}
void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry)
{
llassert(entry->hasVOCacheEntry());
mOctree->insert(entry);
}
void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry)
{
entry->getVOCacheEntry()->setGroup(NULL);
llassert(!entry->getGroup());
}
class LLVOCacheOctreeCull : public LLViewerOctreeCull
{
public:
LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, const LLVector3& shift) : LLViewerOctreeCull(camera), mRegionp(regionp)
{
mLocalShift = shift;
}
virtual S32 frustumCheck(const LLviewerOctreeGroup* group)
{
//S32 res = AABBInRegionFrustumGroupBounds(group);
S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group);
if (res != 0)
{
res = llmin(res, AABBRegionSphereIntersectGroupExtents(group, mLocalShift));
}
return res;
}
virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group)
{
//S32 res = AABBInRegionFrustumObjectBounds(group);
S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group);
if (res != 0)
{
res = llmin(res, AABBRegionSphereIntersectObjectExtents(group, mLocalShift));
}
return res;
}
virtual void processGroup(LLviewerOctreeGroup* base_group)
{
mRegionp->addVisibleGroup(base_group);
}
private:
LLViewerRegion* mRegionp;
LLVector3 mLocalShift; //shift vector from agent space to local region space.
};
S32 LLVOCachePartition::cull(LLCamera &camera)
{
if(!LLViewerRegion::sVOCacheCullingEnabled)
{
return 0;
}
if(mVisitedTime == LLViewerOctreeEntryData::getCurrentFrame())
{
return 0; //already visited.
}
mVisitedTime = LLViewerOctreeEntryData::getCurrentFrame();
((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound();
//localize the camera
LLVector3 region_agent = mRegionp->getOriginAgent();
camera.calcRegionFrustumPlanes(region_agent);
LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent);
culler.traverse(mOctree);
return 0;
}
//-------------------------------------------------------------------
//LLVOCache
//-------------------------------------------------------------------
@ -625,11 +899,10 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca
{
for (S32 i = 0; i < num_entries; i++)
{
LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file);
LLPointer<LLVOCacheEntry> entry = new LLVOCacheEntry(&apr_file);
if (!entry->getLocalID())
{
llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl;
delete entry ;
success = false ;
break ;
}

View File

@ -31,34 +31,95 @@
#include "lldatapacker.h"
#include "lldlinked.h"
#include "lldir.h"
#include "llvieweroctree.h"
//---------------------------------------------------------------------------
// Cache entries
class LLVOCacheEntry;
class LLCamera;
class LLVOCacheEntry
class LLVOCacheEntry : public LLViewerOctreeEntryData
{
public:
enum
{
INACTIVE = 0x00000000, //not visible
IN_QUEUE = 0x00000001, //in visible queue, object to be created
WAITING = 0x00000002, //object creation request sent
ACTIVE = 0x00000004 //object created, and in rendering pipeline.
};
enum
{
ADD_TO_CACHE_TREE = 0x00010000, //has parent
};
struct CompareVOCacheEntry
{
bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs)
{
F32 lpa = lhs->getSceneContribution();
F32 rpa = rhs->getSceneContribution();
//larger pixel area first
if(lpa > rpa)
{
return true;
}
else if(lpa < rpa)
{
return false;
}
else
{
return lhs < rhs;
}
}
};
protected:
~LLVOCacheEntry();
public:
LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp);
LLVOCacheEntry(LLAPRFile* apr_file);
LLVOCacheEntry();
~LLVOCacheEntry();
LLVOCacheEntry();
void setState(U32 state);
void clearState(U32 state) {mState &= ~state;}
void addState(U32 state) {mState |= state;}
bool isState(U32 state) {return (mState & 0xffff) == state;}
bool hasState(U32 state) {return mState & state;}
U32 getState() const {return (mState & 0xffff);}
U32 getFullState() const {return mState;}
U32 getLocalID() const { return mLocalID; }
U32 getCRC() const { return mCRC; }
S32 getHitCount() const { return mHitCount; }
S32 getCRCChangeCount() const { return mCRCChangeCount; }
S32 getMinVisFrameRange()const;
void calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update);
void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;}
F32 getSceneContribution() const { return mSceneContrib;}
void dump() const;
BOOL writeToFile(LLAPRFile* apr_file) const;
void assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp);
LLDataPackerBinaryBuffer *getDP(U32 crc);
LLDataPackerBinaryBuffer *getDP();
void recordHit();
void recordDupe() { mDupeCount++; }
void copyTo(LLVOCacheEntry* new_entry); //copy variables
/*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry);
void addChild(LLVOCacheEntry* entry);
LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];}
S32 getNumOfChildren() {return mChildrenList.size();}
void clearChildrenList() {mChildrenList.clear();}
public:
typedef std::map<U32, LLVOCacheEntry*> vocache_entry_map_t;
typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t;
typedef std::set<LLVOCacheEntry*> vocache_entry_set_t;
typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t;
protected:
U32 mLocalID;
@ -68,6 +129,25 @@ protected:
S32 mCRCChangeCount;
LLDataPackerBinaryBuffer mDP;
U8 *mBuffer;
F32 mSceneContrib; //projected scene contributuion of this object.
S32 mVisFrameRange;
S32 mRepeatedVisCounter; //number of repeatedly visible within a short time.
U32 mState; //high 16 bits reserved for special use.
std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set.
};
class LLVOCachePartition : public LLViewerOctreePartition
{
public:
LLVOCachePartition(LLViewerRegion* regionp);
void addEntry(LLViewerOctreeEntry* entry);
void removeEntry(LLViewerOctreeEntry* entry);
/*virtual*/ S32 cull(LLCamera &camera);
private:
U32 mVisitedTime;
};
//

View File

@ -603,8 +603,8 @@ U32 LLVOGrass::getPartitionType() const
return LLViewerRegion::PARTITION_GRASS;
}
LLGrassPartition::LLGrassPartition()
: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp)
: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_GRASS;
mPartitionType = LLViewerRegion::PARTITION_GRASS;
@ -624,9 +624,9 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count
LLViewerCamera* camera = LLViewerCamera::getInstance();
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
LLDrawable* drawablep = *i;
LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
if (drawablep->isDead())
if (!drawablep || drawablep->isDead())
{
continue;
}
@ -738,8 +738,10 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
//facep->getTexture(),
buffer, fullbright);
info->mExtents[0] = group->mObjectExtents[0];
info->mExtents[1] = group->mObjectExtents[1];
const LLVector4a* exts = group->getObjectExtents();
info->mExtents[0] = exts[0];
info->mExtents[1] = exts[1];
info->mVSize = vsize;
draw_vec.push_back(info);
//for alpha sorting

View File

@ -489,8 +489,8 @@ U32 LLVOPartGroup::getPartitionType() const
return LLViewerRegion::PARTITION_PARTICLE;
}
LLParticlePartition::LLParticlePartition()
: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB)
LLParticlePartition::LLParticlePartition(LLViewerRegion* regionp)
: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp)
{
mRenderPass = LLRenderPass::PASS_ALPHA;
mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES;
@ -499,8 +499,8 @@ LLParticlePartition::LLParticlePartition()
mLODPeriod = 1;
}
LLHUDParticlePartition::LLHUDParticlePartition() :
LLParticlePartition()
LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) :
LLParticlePartition(regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES;
mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE;
@ -510,7 +510,7 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO");
void LLParticlePartition::rebuildGeom(LLSpatialGroup* group)
{
if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY))
{
return;
}
@ -558,9 +558,9 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co
LLViewerCamera* camera = LLViewerCamera::getInstance();
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
LLDrawable* drawablep = *i;
LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
if (drawablep->isDead())
if (!drawablep || drawablep->isDead())
{
continue;
}
@ -699,8 +699,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),
//facep->getTexture(),
buffer, fullbright);
info->mExtents[0] = group->mObjectExtents[0];
info->mExtents[1] = group->mObjectExtents[1];
const LLVector4a* exts = group->getObjectExtents();
info->mExtents[0] = exts[0];
info->mExtents[1] = exts[1];
info->mVSize = vsize;
draw_vec.push_back(info);
//for alpha sorting

View File

@ -1058,8 +1058,8 @@ U32 LLVOSurfacePatch::getPartitionType() const
return LLViewerRegion::PARTITION_TERRAIN;
}
LLTerrainPartition::LLTerrainPartition()
: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB)
LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp)
: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
{
mOcclusionEnabled = FALSE;
mInfiniteFarClip = TRUE;

View File

@ -1290,8 +1290,8 @@ U32 LLVOTree::getPartitionType() const
return LLViewerRegion::PARTITION_TREE;
}
LLTreePartition::LLTreePartition()
: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB)
LLTreePartition::LLTreePartition(LLViewerRegion* regionp)
: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
{
mDrawableType = LLPipeline::RENDER_TYPE_TREE;
mPartitionType = LLViewerRegion::PARTITION_TREE;

View File

@ -3933,8 +3933,8 @@ U32 LLVOVolume::getPartitionType() const
return LLViewerRegion::PARTITION_VOLUME;
}
LLVolumePartition::LLVolumePartition()
: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB)
LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp)
{
mLODPeriod = 32;
mDepthMask = FALSE;
@ -3944,8 +3944,8 @@ LLVolumePartition::LLVolumePartition()
mBufferUsage = GL_DYNAMIC_DRAW_ARB;
}
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK)
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp)
{
mDepthMask = FALSE;
mLODPeriod = 32;
@ -4167,9 +4167,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
group->mLastUpdateViewAngle = group->mViewAngle;
if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY))
if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY))
{
if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate)
if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate)
{
rebuildMesh(group);
}
@ -4207,7 +4207,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
group->mSurfaceArea = 0;
//cache object box size since it might be used for determining visibility
group->mObjectBoxSize = group->mObjectBounds[1].getLength3().getF32();
const LLVector4a* bounds = group->getObjectBounds();
group->mObjectBoxSize = bounds[1].getLength3().getF32();
group->clearDrawMap();
@ -4234,9 +4235,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
//get all the faces into a list
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = *drawable_iter;
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) )
if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) )
{
continue;
}
@ -4640,8 +4641,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
//drawables have been rebuilt, clear rebuild status
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = *drawable_iter;
drawablep->clearState(LLDrawable::REBUILD_ALL);
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if(drawablep)
{
drawablep->clearState(LLDrawable::REBUILD_ALL);
}
}
}
@ -4667,7 +4671,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
llassert(group);
if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))
if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY))
{
LLFastTimer ftm(FTM_REBUILD_VOLUME_VB);
LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers
@ -4680,9 +4684,9 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = *drawable_iter;
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )
{
LLVOVolume* vobj = drawablep->getVOVolume();
vobj->preRebuild();
@ -4748,7 +4752,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ;
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = *drawable_iter;
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if(!drawablep)
{
continue;
}
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
{
LLFace* face = drawablep->getFace(i);
@ -5221,9 +5229,9 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
{
LLDrawable* drawablep = *drawable_iter;
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
if (drawablep->isDead())
if (!drawablep || drawablep->isDead())
{
continue;
}
@ -5261,7 +5269,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun
group->mBufferUsage = usage;
}
LLHUDPartition::LLHUDPartition()
LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) : LLBridgePartition(regionp)
{
mPartitionType = LLViewerRegion::PARTITION_HUD;
mDrawableType = LLPipeline::RENDER_TYPE_HUD;

View File

@ -298,15 +298,15 @@ U32 LLVOVoidWater::getPartitionType() const
return LLViewerRegion::PARTITION_VOIDWATER;
}
LLWaterPartition::LLWaterPartition()
: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB)
LLWaterPartition::LLWaterPartition(LLViewerRegion* regionp)
: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp)
{
mInfiniteFarClip = TRUE;
mDrawableType = LLPipeline::RENDER_TYPE_WATER;
mPartitionType = LLViewerRegion::PARTITION_WATER;
}
LLVoidWaterPartition::LLVoidWaterPartition()
LLVoidWaterPartition::LLVoidWaterPartition(LLViewerRegion* regionp) : LLWaterPartition(regionp)
{
mOcclusionEnabled = FALSE;
mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER;

View File

@ -55,7 +55,7 @@
#include "message.h"
#include "pipeline.h"
#include "llappviewer.h" // for do_disconnect()
#include "llscenemonitor.h"
#include <deque>
#include <queue>
#include <map>
@ -110,6 +110,7 @@ LLWorld::LLWorld() :
gGL.getTexUnit(0)->bind(mDefaultWaterTexturep);
mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
LLViewerRegion::sVOCacheCullingEnabled = (BOOL)gSavedSettings.getBOOL("ObjectCacheViewCullingEnabled");
}
@ -133,6 +134,11 @@ void LLWorld::destroyClass()
{
mEdgeWaterObjects[i] = NULL;
}
//make all visible drawbles invisible.
LLDrawable::incrementVisible();
LLSceneMonitor::getInstance()->destroyClass();
}
@ -599,7 +605,8 @@ void LLWorld::updateVisibilities()
if (part)
{
LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
const LLVector4a* bounds = group->getBounds();
if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1]))
{
mCulledRegionList.erase(curiter);
mVisibleRegionList.push_back(regionp);
@ -622,7 +629,8 @@ void LLWorld::updateVisibilities()
if (part)
{
LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
const LLVector4a* bounds = group->getBounds();
if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1]))
{
regionp->calculateCameraDistance();
regionp->getLand().updatePatchVisibilities(gAgent);
@ -644,8 +652,8 @@ void LLWorld::updateVisibilities()
void LLWorld::updateRegions(F32 max_update_time)
{
LLTimer update_timer;
BOOL did_one = FALSE;
BOOL did_one = FALSE;
// Perform idle time updates for the regions (and associated surfaces)
for (region_list_t::iterator iter = mRegionList.begin();
iter != mRegionList.end(); ++iter)
@ -660,6 +668,13 @@ void LLWorld::updateRegions(F32 max_update_time)
did_one = TRUE;
}
}
mNumOfActiveCachedObjects = 0;
for (region_list_t::iterator iter = mRegionList.begin();
iter != mRegionList.end(); ++iter)
{
mNumOfActiveCachedObjects += (*iter)->getNumOfActiveCachedObjects();
}
}
void LLWorld::updateParticles()

View File

@ -144,6 +144,7 @@ public:
U64 getSpaceTimeUSec() const;
void getInfo(LLSD& info);
U32 getNumOfActiveCachedObjects() const {return mNumOfActiveCachedObjects;}
public:
typedef std::list<LLViewerRegion*> region_list_t;
@ -181,7 +182,7 @@ private:
S32 mLastPacketsIn;
S32 mLastPacketsOut;
S32 mLastPacketsLost;
U32 mNumOfActiveCachedObjects;
U64 mSpaceTimeUSec;
BOOL mClassicCloudsEnabled;

View File

@ -86,6 +86,7 @@
#include "llviewerregion.h" // for audio debugging.
#include "llviewerwindow.h" // For getSpinAxis
#include "llvoavatarself.h"
#include "llvocache.h"
#include "llvoground.h"
#include "llvosky.h"
#include "llvotree.h"
@ -111,6 +112,7 @@
#include "llfloaterpathfindingconsole.h"
#include "llfloaterpathfindingcharacters.h"
#include "llpathfindingpathtool.h"
#include "llscenemonitor.h"
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
@ -1410,18 +1412,18 @@ S32 LLPipeline::setLightingDetail(S32 level)
return mLightingDetail;
}
class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable>
class LLOctreeDirtyTexture : public OctreeTraveler
{
public:
const std::set<LLViewerFetchedTexture*>& mTextures;
LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { }
virtual void visit(const LLOctreeNode<LLDrawable>* node)
virtual void visit(const OctreeNode* node)
{
LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty())
if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty())
{
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
{
@ -1610,11 +1612,9 @@ void LLPipeline::addPool(LLDrawPool *new_poolp)
void LLPipeline::allocDrawable(LLViewerObject *vobj)
{
LLDrawable *drawable = new LLDrawable();
LLDrawable *drawable = new LLDrawable(vobj);
vobj->mDrawable = drawable;
drawable->mVObjp = vobj;
//encompass completely sheared objects by taking
//the most extreme point possible (<1,1,0.5>)
drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length());
@ -2038,7 +2038,7 @@ void check_references(LLSpatialGroup* group, LLDrawable* drawable)
{
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
if (drawable == *i)
if (drawable == (LLDrawable*)(*i)->getDrawable())
{
llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
}
@ -2060,8 +2060,11 @@ void check_references(LLSpatialGroup* group, LLFace* face)
{
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
LLDrawable* drawable = *i;
check_references(drawable, face);
LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable();
if(drawable)
{
check_references(drawable, face);
}
}
}
@ -2385,6 +2388,13 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
}
}
}
//scan the VO Cache tree
LLVOCachePartition* vo_part = region->getVOCachePartition();
if(vo_part)
{
vo_part->cull(camera);
}
}
if (bound_shader)
@ -2452,14 +2462,15 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera)
return;
}
const LLVector4a* bounds = group->getBounds();
if (sMinRenderSize > 0.f &&
llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize)
llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize)
{
return;
}
assertInitialized();
if (!group->mSpatialPartition->mRenderByGroup)
{ //render by drawable
sCull->pushDrawableGroup(group);
@ -3041,14 +3052,14 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
if (priority)
{
if (!group->isState(LLSpatialGroup::IN_BUILD_Q1))
if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1))
{
llassert_always(!mGroupQ1Locked);
mGroupQ1.push_back(group);
group->setState(LLSpatialGroup::IN_BUILD_Q1);
if (group->isState(LLSpatialGroup::IN_BUILD_Q2))
if (group->hasState(LLSpatialGroup::IN_BUILD_Q2))
{
LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group);
if (iter != mGroupQ2.end())
@ -3059,7 +3070,7 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
}
}
}
else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1))
{
llassert_always(!mGroupQ2Locked);
mGroupQ2.push_back(group);
@ -3134,7 +3145,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
group->setVisible();
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
markVisible(*i, camera);
markVisible((LLDrawable*)(*i)->getDrawable(), camera);
}
if (!sDelayVBUpdate)
@ -3212,7 +3223,9 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
postSort(camera);
postSort(camera);
LLSceneMonitor::getInstance()->fetchQueryResult();
}
void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
@ -3221,8 +3234,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
{
for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
{
LLDrawable* drawablep = *i;
stateSort(drawablep, camera);
stateSort((LLDrawable*)(*i)->getDrawable(), camera);
}
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
@ -3341,7 +3353,10 @@ void forAllDrawables(LLCullResult::sg_iterator begin,
{
for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j)
{
func(*j);
if((*j)->hasDrawable())
{
func((LLDrawable*)(*j)->getDrawable());
}
}
}
}
@ -3569,7 +3584,7 @@ void LLPipeline::postSort(LLCamera& camera)
continue;
}
if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY))
if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY))
{ //no way this group is going to be drawable without a rebuild
group->rebuildGeom();
}

View File

@ -1989,6 +1989,16 @@
function="Advanced.ToggleConsole"
parameter="scene view" />
</menu_item_check>
<menu_item_check
label="Scene Loading Monitor"
name="Scene Loading Monitor">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="scene monitor" />
<menu_item_check.on_click
function="Advanced.ToggleConsole"
parameter="scene monitor" />
</menu_item_check>
<menu_item_call
enabled="false"
visible="false"