Files
SingularityViewer/indra/newview/lldrawpoolavatar.cpp
Shyotl e756140e1d Innitial commit of experimental v2 texture system port work. Compiles and runs on windows, at least. Fixing bugs as they come.
Need to test:
localassetbrowser
preview related floaters
hgfloatertexteditor
maps
media textures! Currently very hacky
web browser
alpha masks on avatars
bumpmaps
Are all sky components appearing?
LLViewerDynamicTexture (texture baking, browser, animated textures, anim previews, etc)
Snapshot related features
Customize avatar
vfs floater
UI textures in general
Texture priority issues
2011-03-31 03:22:01 -05:00

903 lines
20 KiB
C++

/**
* @file lldrawpoolavatar.cpp
* @brief LLDrawPoolAvatar class implementation
*
* $LicenseInfo:firstyear=2002&license=viewergpl$
*
* Copyright (c) 2002-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lldrawpoolavatar.h"
#include "llrender.h"
#include "llvoavatar.h"
#include "m3math.h"
#include "llagent.h"
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
#include "llviewercamera.h"
#include "llviewerregion.h"
#include "noise.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
#include "llappviewer.h"
#include "llrendersphere.h"
#include "llviewerpartsim.h"
static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
static U32 sBufferUsage = GL_STREAM_DRAW_ARB;
static U32 sShaderLevel = 0;
static LLGLSLShader* sVertexProgram = NULL;
BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
extern BOOL gUseGLPick;
F32 CLOTHING_GRAVITY_EFFECT = 0.7f;
F32 CLOTHING_ACCEL_FORCE_FACTOR = 0.2f;
const S32 NUM_TEST_AVATARS = 30;
const S32 MIN_PIXEL_AREA_2_PASS_SKINNING = 500000000;
// Format for gAGPVertices
// vertex format for bumpmapping:
// vertices 12
// pad 4
// normals 12
// pad 4
// texcoords0 8
// texcoords1 8
// total 48
//
// for no bumpmapping
// vertices 12
// texcoords 8
// normals 12
// total 32
//
S32 AVATAR_OFFSET_POS = 0;
S32 AVATAR_OFFSET_NORMAL = 16;
S32 AVATAR_OFFSET_TEX0 = 32;
S32 AVATAR_OFFSET_TEX1 = 40;
S32 AVATAR_VERTEX_BYTES = 48;
BOOL gAvatarEmbossBumpMap = FALSE;
static BOOL sRenderingSkinned = FALSE;
S32 normal_channel = -1;
S32 specular_channel = -1;
LLDrawPoolAvatar::LLDrawPoolAvatar() :
LLFacePool(POOL_AVATAR)
{
//LLDebugVarMessageBox::show("acceleration", &CLOTHING_ACCEL_FORCE_FACTOR, 10.f, 0.1f);
//LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f);
}
//-----------------------------------------------------------------------------
// instancePool()
//-----------------------------------------------------------------------------
LLDrawPool *LLDrawPoolAvatar::instancePool()
{
return new LLDrawPoolAvatar();
}
BOOL gRenderAvatar = TRUE;
S32 LLDrawPoolAvatar::getVertexShaderLevel() const
{
return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
}
void LLDrawPoolAvatar::prerender()
{
mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
sShaderLevel = mVertexShaderLevel;
if (sShaderLevel > 0)
{
sBufferUsage = GL_DYNAMIC_DRAW_ARB;
//sBufferUsage = GL_STATIC_DRAW_ARB;
}
else
{
sBufferUsage = GL_STREAM_DRAW_ARB;
}
}
LLMatrix4& LLDrawPoolAvatar::getModelView()
{
static LLMatrix4 ret;
ret.initRows(LLVector4(gGLModelView+0),
LLVector4(gGLModelView+4),
LLVector4(gGLModelView+8),
LLVector4(gGLModelView+12));
return ret;
}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
S32 LLDrawPoolAvatar::getNumDeferredPasses()
{
return getNumPasses();
}
void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
{
sSkipTransparent = TRUE;
if (LLPipeline::sImpostorRender)
{
beginDeferredSkinned();
return;
}
switch (pass)
{
case 0:
beginDeferredImpostor();
break;
case 1:
beginDeferredRigid();
break;
case 2:
beginDeferredSkinned();
break;
}
}
void LLDrawPoolAvatar::endDeferredPass(S32 pass)
{
sSkipTransparent = FALSE;
if (LLPipeline::sImpostorRender)
{
endDeferredSkinned();
return;
}
switch (pass)
{
case 0:
endDeferredImpostor();
break;
case 1:
endDeferredRigid();
break;
case 2:
endDeferredSkinned();
break;
}
}
void LLDrawPoolAvatar::renderDeferred(S32 pass)
{
render(pass);
}
S32 LLDrawPoolAvatar::getNumPostDeferredPasses()
{
return 1;
}
void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
{
sSkipOpaque = TRUE;
sShaderLevel = mVertexShaderLevel;
sVertexProgram = &gDeferredAvatarAlphaProgram;
sRenderingSkinned = TRUE;
gPipeline.bindDeferredShader(*sVertexProgram);
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)
{
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
sRenderingSkinned = FALSE;
sSkipOpaque = FALSE;
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
gPipeline.unbindDeferredShader(*sVertexProgram);
sShaderLevel = mVertexShaderLevel;
}
void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
{
render(2); //pass 2 = skinned
}
S32 LLDrawPoolAvatar::getNumShadowPasses()
{
return 1;
}
void LLDrawPoolAvatar::beginShadowPass(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
sVertexProgram = &gDeferredAvatarShadowProgram;
if (sShaderLevel > 0)
{
gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
glColor4f(1,1,1,1);
if ((sShaderLevel > 0)) // for hardware blending
{
sRenderingSkinned = TRUE;
sVertexProgram->bind();
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
}
void LLDrawPoolAvatar::endShadowPass(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
if (sShaderLevel > 0)
{
sRenderingSkinned = FALSE;
sVertexProgram->unbind();
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
}
void LLDrawPoolAvatar::renderShadow(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR);
if (!gRenderAvatar)
{
return;
}
if (mDrawFace.empty())
{
return;
}
const LLFace *facep = mDrawFace[0];
if (!facep->getDrawable())
{
return;
}
LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull())
{
return;
}
BOOL impostor = avatarp->isImpostor();
if (impostor)
{
return;
}
if (sShaderLevel > 0)
{
gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
}
S32 LLDrawPoolAvatar::getNumPasses()
{
return LLPipeline::sImpostorRender ? 1 : 3;
}
void LLDrawPoolAvatar::render(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
renderAvatars(NULL, 2);
return;
}
renderAvatars(NULL, pass); // render all avatars
}
void LLDrawPoolAvatar::beginRenderPass(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
//reset vertex buffer mappings
LLVertexBuffer::unbind();
if (LLPipeline::sImpostorRender)
{
beginSkinned();
return;
}
switch (pass)
{
case 0:
beginImpostor();
break;
case 1:
beginRigid();
break;
case 2:
beginSkinned();
break;
}
}
void LLDrawPoolAvatar::endRenderPass(S32 pass)
{
LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS);
if (LLPipeline::sImpostorRender)
{
endSkinned();
return;
}
switch (pass)
{
case 0:
endImpostor();
break;
case 1:
endRigid();
break;
case 2:
endSkinned();
}
}
void LLDrawPoolAvatar::beginImpostor()
{
if (!LLPipeline::sReflectionRender)
{
LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f);
LLVOAvatar::sNumVisibleAvatars = 0;
}
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
}
void LLDrawPoolAvatar::endImpostor()
{
gPipeline.enableLightsDynamic();
}
void LLDrawPoolAvatar::beginRigid()
{
if (gPipeline.canUseVertexShaders())
{
if (LLPipeline::sUnderWaterRender)
{
sVertexProgram = &gObjectSimpleWaterProgram;
}
else
{
sVertexProgram = &gObjectSimpleProgram;
}
if (sVertexProgram != NULL)
{ //eyeballs render with the specular shader
sVertexProgram->bind();
}
}
else
{
sVertexProgram = NULL;
}
}
void LLDrawPoolAvatar::endRigid()
{
sShaderLevel = mVertexShaderLevel;
if (sVertexProgram != NULL)
{
sVertexProgram->unbind();
}
}
void LLDrawPoolAvatar::beginDeferredImpostor()
{
if (!LLPipeline::sReflectionRender)
{
LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f);
LLVOAvatar::sNumVisibleAvatars = 0;
}
sVertexProgram = &gDeferredImpostorProgram;
normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
sVertexProgram->bind();
}
void LLDrawPoolAvatar::endDeferredImpostor()
{
sShaderLevel = mVertexShaderLevel;
sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
sVertexProgram->unbind();
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolAvatar::beginDeferredRigid()
{
sVertexProgram = &gDeferredDiffuseProgram;
sVertexProgram->bind();
}
void LLDrawPoolAvatar::endDeferredRigid()
{
sShaderLevel = mVertexShaderLevel;
sVertexProgram->unbind();
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolAvatar::beginSkinned()
{
if (sShaderLevel > 0)
{
if (LLPipeline::sUnderWaterRender)
{
sVertexProgram = &gAvatarWaterProgram;
sShaderLevel = llmin((U32) 1, sShaderLevel);
}
else
{
sVertexProgram = &gAvatarProgram;
}
}
else
{
if (LLPipeline::sUnderWaterRender)
{
sVertexProgram = &gObjectSimpleWaterProgram;
}
else
{
sVertexProgram = &gObjectSimpleProgram;
}
}
if (sShaderLevel > 0) // for hardware blending
{
sRenderingSkinned = TRUE;
sVertexProgram->bind();
if (sShaderLevel >= SHADER_LEVEL_CLOTH)
{
enable_cloth_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING]);
}
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
if (sShaderLevel >= SHADER_LEVEL_BUMP)
{
enable_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL]);
}
sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
gGL.getTexUnit(0)->activate();
}
else
{
if(gPipeline.canUseVertexShaders())
{
// software skinning, use a basic shader for windlight.
// TODO: find a better fallback method for software skinning.
sVertexProgram->bind();
}
}
}
void LLDrawPoolAvatar::endSkinned()
{
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
if (sShaderLevel > 0)
{
sRenderingSkinned = FALSE;
sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
gGL.getTexUnit(0)->activate();
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
if (sShaderLevel >= SHADER_LEVEL_BUMP)
{
disable_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL]);
}
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
disable_cloth_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING]);
}
sVertexProgram->unbind();
sShaderLevel = mVertexShaderLevel;
}
else
{
if(gPipeline.canUseVertexShaders())
{
// software skinning, use a basic shader for windlight.
// TODO: find a better fallback method for software skinning.
sVertexProgram->unbind();
}
}
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolAvatar::beginDeferredSkinned()
{
sShaderLevel = mVertexShaderLevel;
sVertexProgram = &gDeferredAvatarProgram;
sRenderingSkinned = TRUE;
sVertexProgram->bind();
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolAvatar::endDeferredSkinned()
{
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
sRenderingSkinned = FALSE;
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
sVertexProgram->unbind();
sShaderLevel = mVertexShaderLevel;
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
{
if (pass == -1)
{
for (S32 i = 1; i < getNumPasses(); i++)
{ //skip foot shadows
prerender();
beginRenderPass(i);
renderAvatars(single_avatar, i);
endRenderPass(i);
}
return;
}
if (!gRenderAvatar)
{
return;
}
if (mDrawFace.empty() && !single_avatar)
{
return;
}
LLVOAvatar *avatarp;
if (single_avatar)
{
avatarp = single_avatar;
}
else
{
const LLFace *facep = mDrawFace[0];
if (!facep->getDrawable())
{
return;
}
avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
}
if (avatarp->isDead() || avatarp->mDrawable.isNull())
{
return;
}
if (!single_avatar && !avatarp->isFullyLoaded() )
{
if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0))
{
// debug code to draw a sphere in place of avatar
gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep.get());
gGL.setColorMask(true, true);
LLVector3 pos = avatarp->getPositionAgent();
gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f);
gGL.pushMatrix();
gGL.translatef((F32)(pos.mV[VX]),
(F32)(pos.mV[VY]),
(F32)(pos.mV[VZ]));
gGL.scalef(0.15f, 0.15f, 0.3f);
gSphere.render();
gGL.popMatrix();
gGL.setColorMask(true, false);
}
// don't render please
return;
}
BOOL impostor = avatarp->isImpostor() && !single_avatar;
if (impostor && pass != 0)
{ //don't draw anything but the impostor for impostored avatars
return;
}
if (pass == 0 && !impostor && LLPipeline::sUnderWaterRender)
{ //don't draw foot shadows under water
return;
}
LLOverrideFaceColor color(this, 1.0f, 1.0f, 1.0f, 1.0f);
if (pass == 0)
{
if (!LLPipeline::sReflectionRender)
{
LLVOAvatar::sNumVisibleAvatars++;
}
if (impostor)
{
if (LLPipeline::sRenderDeferred && avatarp->mImpostor.isComplete())
{
if (normal_channel > -1)
{
avatarp->mImpostor.bindTexture(2, normal_channel);
}
if (specular_channel > -1)
{
avatarp->mImpostor.bindTexture(1, specular_channel);
}
}
avatarp->renderImpostor();
}
else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred)
{
avatarp->renderFootShadows();
}
return;
}
if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview, 3=morph view
{
gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f));
}
if (pass == 1)
{
// render rigid meshes (eyeballs) first
avatarp->renderRigid();
return;
}
if (sShaderLevel > 0)
{
gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
LLMatrix4 rot_mat;
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
rot_mat *= cfr;
LLVector4 wind;
wind.setVec(avatarp->mWindVec);
wind.mV[VW] = 0;
wind = wind * rot_mat;
wind.mV[VW] = avatarp->mWindVec.mV[VW];
sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_WIND, wind.mV);
F32 phase = -1.f * (avatarp->mRipplePhase);
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
LLVector4 sin_params(freq, freq, freq, phase);
sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_SINWAVE, sin_params.mV);
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
gravity = gravity * rot_mat;
sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_GRAVITY, gravity.mV);
}
if( !single_avatar || (avatarp == single_avatar) )
{
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
}
}
//-----------------------------------------------------------------------------
// renderForSelect()
//-----------------------------------------------------------------------------
void LLDrawPoolAvatar::renderForSelect()
{
if (!gRenderAvatar)
{
return;
}
if (mDrawFace.empty())
{
return;
}
const LLFace *facep = mDrawFace[0];
if (!facep->getDrawable())
{
return;
}
LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull())
{
return;
}
S32 curr_shader_level = getVertexShaderLevel();
S32 name = avatarp->mDrawable->getVObj()->mGLName;
LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name);
BOOL impostor = avatarp->isImpostor();
if (impostor)
{
gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_COLOR);
gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
avatarp->renderImpostor(color);
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
return;
}
sVertexProgram = &gAvatarPickProgram;
if (curr_shader_level > 0)
{
gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
glColor4ubv(color.mV);
if (curr_shader_level > 0) // for hardware blending
{
sRenderingSkinned = TRUE;
sVertexProgram->bind();
enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
if (curr_shader_level > 0)
{
sRenderingSkinned = FALSE;
sVertexProgram->unbind();
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
// restore texture mode
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
//-----------------------------------------------------------------------------
// getDebugTexture()
//-----------------------------------------------------------------------------
LLViewerTexture *LLDrawPoolAvatar::getDebugTexture()
{
if (mReferences.empty())
{
return NULL;
}
LLFace *face = mReferences[0];
if (!face->getDrawable())
{
return NULL;
}
const LLViewerObject *objectp = face->getDrawable()->getVObj();
// Avatar should always have at least 1 (maybe 3?) TE's.
return objectp->getTEImage(0);
}
LLColor3 LLDrawPoolAvatar::getDebugColor() const
{
return LLColor3(0.f, 1.f, 0.f);
}
LLVertexBufferAvatar::LLVertexBufferAvatar()
: LLVertexBuffer(sDataMask,
//LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 ?
//GL_DYNAMIC_DRAW_ARB :
GL_STREAM_DRAW_ARB)
{
}
void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const
{
if (sRenderingSkinned)
{
volatile U8* base = useVBOs() ? NULL : mMappedData;
glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0));
glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL]));
glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0]));
set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT]));
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP)
{
set_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
}
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)
{
set_vertex_clothing_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
}
}
else
{
LLVertexBuffer::setupVertexBuffer(data_mask);
}
}