summaryrefslogtreecommitdiff
path: root/indra/newview/llvoavatar.cpp
diff options
context:
space:
mode:
authorBrad Kittenbrink <brad@lindenlab.com>2008-02-27 18:58:14 +0000
committerBrad Kittenbrink <brad@lindenlab.com>2008-02-27 18:58:14 +0000
commit6d52efe452aa8469e0343da1c7d108f3f52ab651 (patch)
treea87be48e9840d7fc1f7ee514d7c7f994e71fdb3c /indra/newview/llvoavatar.cpp
parent6027ad2630b8650cabcf00628ee9b0d25bedd67f (diff)
Merge of windlight into release (QAR-286). This includes all changes in
windlight14 which have passed QA (up through r79932). svn merge -r 80831:80833 svn+ssh://svn.lindenlab.com/svn/linden/branches/merge_windlight14_r80620
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r--indra/newview/llvoavatar.cpp1006
1 files changed, 484 insertions, 522 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 90e61426e9..99cf3a8046 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -37,6 +37,7 @@
#include "llvoavatar.h"
+#include "llglimmediate.h"
#include "audioengine.h"
#include "imageids.h"
#include "indra_constants.h"
@@ -113,6 +114,7 @@
#include "llwearablelist.h"
#include "llworld.h"
#include "pipeline.h"
+#include "llspatialpartition.h"
#include "llglslshader.h"
#include "llappviewer.h"
#include "lscript_byteformat.h"
@@ -255,6 +257,7 @@ S32 LLVOAvatar::sMaxOtherAvatarsToComposite = 1; // Only this many avatars (oth
LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames;
LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime;
S32 LLVOAvatar::sScratchTexBytes = 0;
+F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
@@ -279,8 +282,8 @@ BOOL LLVOAvatar::sShowAnimationDebug = FALSE;
BOOL LLVOAvatar::sShowFootPlane = FALSE;
BOOL LLVOAvatar::sShowCollisionVolumes = FALSE;
BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
-BOOL LLVOAvatar::sAvatarLoadTest = FALSE;
F32 LLVOAvatar::sLODFactor = 1.f;
+BOOL LLVOAvatar::sUseImpostors = TRUE;
BOOL LLVOAvatar::sJointDebug = FALSE;
S32 LLVOAvatar::sCurJoint = 0;
@@ -679,7 +682,9 @@ LLVOAvatar::LLVOAvatar(
mCulled( FALSE ),
mTexSkinColor( NULL ),
mTexHairColor( NULL ),
- mTexEyeColor( NULL )
+ mTexEyeColor( NULL ),
+ mNeedsSkin(FALSE),
+ mUpdatePeriod(1)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
@@ -730,6 +735,11 @@ LLVOAvatar::LLVOAvatar(
mIsSelf = FALSE;
}
+ mNeedsImpostorUpdate = TRUE;
+ mNeedsAnimUpdate = TRUE;
+
+ mImpostorDistance = 0;
+
setNumTEs(TEX_NUM_ENTRIES);
mbCanSelect = TRUE;
@@ -1271,16 +1281,6 @@ void LLVOAvatar::dumpBakedStatus()
}
//static
-void LLVOAvatar::cleanupVertexPrograms()
-{
-}
-
-//static
-void LLVOAvatar::initVertexPrograms()
-{
-}
-
-//static
void LLVOAvatar::restoreGL()
{
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
@@ -1301,7 +1301,19 @@ void LLVOAvatar::restoreGL()
void LLVOAvatar::destroyGL()
{
deleteCachedImages();
- cleanupVertexPrograms();
+
+ resetImpostors();
+}
+
+//static
+void LLVOAvatar::resetImpostors()
+{
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*) *iter;
+ avatar->mImpostor.release();
+ }
}
// static
@@ -1454,17 +1466,106 @@ void LLVOAvatar::cleanupClass()
sXMLTree.cleanup();
}
+const LLVector3 LLVOAvatar::getRenderPosition() const
+{
+ if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
+ {
+ return getPositionAgent();
+ }
+ else if (isRoot())
+ {
+ return mDrawable->getPositionAgent();
+ }
+ else
+ {
+ return getPosition() * mDrawable->getParent()->getRenderMatrix();
+ }
+}
+
+void LLVOAvatar::updateDrawable(BOOL force_damped)
+{
+ clearChanged(SHIFTED);
+}
+
+void LLVOAvatar::onShift(const LLVector3& shift_vector)
+{
+ mLastAnimExtents[0] += shift_vector;
+ mLastAnimExtents[1] += shift_vector;
+ mNeedsImpostorUpdate = TRUE;
+ mNeedsAnimUpdate = TRUE;
+}
void LLVOAvatar::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax)
{
- LLVector3 center = getRenderPosition();
- LLVector3 size = getScale();
- //maximum amount an animation can move avatar from drawable position
- LLVector3 animation_buffer(5, 5, 5);
+ if (isImpostor() && !needsImpostorUpdate())
+ {
+ LLVector3 delta = getRenderPosition() -
+ ((LLVector3(mDrawable->getPositionGroup())-mImpostorOffset));
+
+ newMin = mLastAnimExtents[0] + delta;
+ newMax = mLastAnimExtents[1] + delta;
+ }
+ else
+ {
+ getSpatialExtents(newMin,newMax);
+ mLastAnimExtents[0] = newMin;
+ mLastAnimExtents[1] = newMax;
+ LLVector3 pos_group = (newMin+newMax)*0.5f;
+ mImpostorOffset = pos_group-getRenderPosition();
+ mDrawable->setPositionGroup(pos_group);
+ }
+}
+
+void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
+{
+ LLVector3 buffer(0.25f, 0.25f, 0.25f);
+ LLVector3 pos = getRenderPosition();
+ newMin = pos - buffer;
+ newMax = pos + buffer;
+
+ //stretch bounding box by joint positions
+ for (mesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i)
+ {
+ LLPolyMesh* mesh = i->second;
+ for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++)
+ {
+ update_min_max(newMin, newMax,
+ mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation());
+ }
+ }
+
+ //stretch bounding box by attachments
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+
+ if(!attachment->getValid())
+ {
+ continue ;
+ }
- newMin.setVec((center-size)-animation_buffer);
- newMax.setVec(center+size+animation_buffer);
- mDrawable->setPositionGroup((newMin + newMax) * 0.5f);
+ LLViewerObject* object = attachment->getObject();
+ if (object && !object->isHUDAttachment())
+ {
+ LLDrawable* drawable = object->mDrawable;
+ if (drawable)
+ {
+ LLSpatialBridge* bridge = drawable->getSpatialBridge();
+ if (bridge)
+ {
+ const LLVector3* ext = bridge->getSpatialExtents();
+ update_min_max(newMin,newMax,ext[0]);
+ update_min_max(newMin,newMax,ext[1]);
+ }
+ }
+ }
+ }
+
+ //pad bounding box
+ newMin -= buffer;
+ newMax += buffer;
}
@@ -2080,6 +2181,7 @@ void LLVOAvatar::updateMeshData()
{
if (mDrawable.notNull())
{
+ stop_glerror();
LLFace* facep = mDrawable->getFace(0);
U32 num_vertices = 0;
@@ -2102,6 +2204,7 @@ void LLVOAvatar::updateMeshData()
facep->mVertexBuffer = new LLVertexBufferAvatar();
facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
+
facep->setGeomIndex(0);
facep->setIndicesIndex(0);
@@ -2120,6 +2223,9 @@ void LLVOAvatar::updateMeshData()
mSkirtLOD.updateFaceData(facep, mAdjustedPixelArea);
mUpperBodyLOD.updateFaceData(facep, mAdjustedPixelArea);
mHairLOD.updateFaceData(facep, mAdjustedPixelArea, TRUE);
+
+ stop_glerror();
+ facep->mVertexBuffer->setBuffer(0);
}
}
@@ -2286,9 +2392,6 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// force immediate pixel area update on avatars using last frames data (before drawable or camera updates)
setPixelAreaAndAngle(gAgent);
- // Update the LOD of the joints
- //static const F32 UPDATE_TIME = .5f;
-
// force asynchronous drawable update
if(mDrawable.notNull() && !gNoRender)
{
@@ -2346,86 +2449,87 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// store off last frame's root position to be consistent with camera position
LLVector3 root_pos_last = mRoot.getWorldPosition();
- updateCharacter(agent);
-
- //Ventrella
- bool voiceEnabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
- // disable voice visualizer when in mouselook
- mVoiceVisualizer->setVoiceEnabled( voiceEnabled && !(mIsSelf && gAgent.cameraMouselook()) );
- if ( voiceEnabled )
- {
- //----------------------------------------------------------------
- // Only do gesture triggering for your own avatar, and only when you're in a proximal channel.
- //----------------------------------------------------------------
- if( mIsSelf )
- {
- //----------------------------------------------------------------------------------------
- // The following takes the voice signal and uses that to trigger gesticulations.
- //----------------------------------------------------------------------------------------
- int lastGesticulationLevel = mCurrentGesticulationLevel;
- mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel();
-
- //---------------------------------------------------------------------------------------------------
- // If "current gesticulation level" changes, we catch this, and trigger the new gesture
- //---------------------------------------------------------------------------------------------------
- if ( lastGesticulationLevel != mCurrentGesticulationLevel )
+ BOOL detailed_update = updateCharacter(agent);
+
+ {
+ //Ventrella
+ bool voiceEnabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
+ // disable voice visualizer when in mouselook
+ mVoiceVisualizer->setVoiceEnabled( voiceEnabled && !(mIsSelf && gAgent.cameraMouselook()) );
+ if ( voiceEnabled )
+ {
+ //----------------------------------------------------------------
+ // Only do gesture triggering for your own avatar, and only when you're in a proximal channel.
+ //----------------------------------------------------------------
+ if( mIsSelf )
{
- if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF )
+ //----------------------------------------------------------------------------------------
+ // The following takes the voice signal and uses that to trigger gesticulations.
+ //----------------------------------------------------------------------------------------
+ int lastGesticulationLevel = mCurrentGesticulationLevel;
+ mCurrentGesticulationLevel = mVoiceVisualizer->getCurrentGesticulationLevel();
+
+ //---------------------------------------------------------------------------------------------------
+ // If "current gesticulation level" changes, we catch this, and trigger the new gesture
+ //---------------------------------------------------------------------------------------------------
+ if ( lastGesticulationLevel != mCurrentGesticulationLevel )
{
- LLString gestureString = "unInitialized";
- if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; }
- else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; }
- else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; }
- else { printf( "oops - CurrentGesticulationLevel can be only 0, 1, or 2\n" ); }
-
- // this is the call that Karl S. created for triggering gestures from within the code.
- gGestureManager.triggerAndReviseString( gestureString );
+ if ( mCurrentGesticulationLevel != VOICE_GESTICULATION_LEVEL_OFF )
+ {
+ LLString gestureString = "unInitialized";
+ if ( mCurrentGesticulationLevel == 0 ) { gestureString = "/voicelevel1"; }
+ else if ( mCurrentGesticulationLevel == 1 ) { gestureString = "/voicelevel2"; }
+ else if ( mCurrentGesticulationLevel == 2 ) { gestureString = "/voicelevel3"; }
+ else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; }
+
+ // this is the call that Karl S. created for triggering gestures from within the code.
+ gGestureManager.triggerAndReviseString( gestureString );
+ }
}
- }
-
- } //if( mIsSelf )
+
+ } //if( mIsSelf )
- //-----------------------------------------------------------------------------------------------------------------
- // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer.
- // Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol.
- //
- // Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
- // "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
- //-----------------------------------------------------------------------------------------------------------------
- if ( gVoiceClient->getIsSpeaking( mID ) )
- {
- if ( ! mVoiceVisualizer->getCurrentlySpeaking() )
+ //-----------------------------------------------------------------------------------------------------------------
+ // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer.
+ // Also, here we trigger voice visualizer start and stop speaking, so it can animate the voice symbol.
+ //
+ // Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
+ // "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
+ //-----------------------------------------------------------------------------------------------------------------
+ if ( gVoiceClient->getIsSpeaking( mID ) )
{
- mVoiceVisualizer->setStartSpeaking();
-
- //printf( "gAwayTimer.reset();\n" );
- }
+ if ( ! mVoiceVisualizer->getCurrentlySpeaking() )
+ {
+ mVoiceVisualizer->setStartSpeaking();
+
+ //printf( "gAwayTimer.reset();\n" );
+ }
- mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
+ mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
- if( mIsSelf )
- {
- gAgent.clearAFK();
+ if( mIsSelf )
+ {
+ gAgent.clearAFK();
+ }
}
- }
- else
- {
- if ( mVoiceVisualizer->getCurrentlySpeaking() )
+ else
{
- mVoiceVisualizer->setStopSpeaking();
+ if ( mVoiceVisualizer->getCurrentlySpeaking() )
+ {
+ mVoiceVisualizer->setStopSpeaking();
+ }
}
- }
- //--------------------------------------------------------------------------------------------
- // here we get the approximate head position and set as sound source for the voice symbol
- // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
- //--------------------------------------------------------------------------------------------
- LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
- mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
+ //--------------------------------------------------------------------------------------------
+ // here we get the approximate head position and set as sound source for the voice symbol
+ // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
+ //--------------------------------------------------------------------------------------------
+ LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
+ mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
- }//if ( voiceEnabled )
+ }//if ( voiceEnabled )
+ }
//End Ventrella
-
if (LLVOAvatar::sJointDebug)
{
@@ -2446,7 +2550,10 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE);
}
+ BOOL visible = isVisible() || mNeedsAnimUpdate;
+
// update attachments positions
+ if (detailed_update || !sUseImpostors)
{
LLFastTimer t(LLFastTimer::FTM_ATTACHMENT_UPDATE);
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
@@ -2456,8 +2563,9 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
LLViewerJointAttachment* attachment = curiter->second;
LLViewerObject *attached_object = attachment->getObject();
- BOOL visibleAttachment = isVisible() || !(attached_object && attached_object->mDrawable->getSpatialBridge()
- && (attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+ BOOL visibleAttachment = visible || (attached_object &&
+ !(attached_object->mDrawable->getSpatialBridge() &&
+ attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
{
@@ -2470,10 +2578,61 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
}
- attached_object->updateText();
+
+ LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
+ if (bridge)
+ {
+ gPipeline.updateMoveNormalAsync(bridge);
+ }
+ attached_object->updateText();
+ }
+ }
+ }
+
+ mNeedsAnimUpdate = FALSE;
+
+ if (isImpostor() && !mNeedsImpostorUpdate)
+ {
+ LLVector3 ext[2];
+ F32 distance;
+ LLVector3 angle;
+
+ getImpostorValues(ext, angle, distance);
+
+ for (U32 i = 0; i < 3 && !mNeedsImpostorUpdate; i++)
+ {
+ F32 cur_angle = angle.mV[i];
+ F32 old_angle = mImpostorAngle.mV[i];
+ F32 angle_diff = fabsf(cur_angle-old_angle);
+
+ if (angle_diff > 3.14159f/16.f)
+ {
+ mNeedsImpostorUpdate = TRUE;
+ }
+ }
+
+ if (detailed_update && !mNeedsImpostorUpdate)
+ { //update impostor if view angle, distance, or bounding box change
+ //significantly
+
+ F32 dist_diff = fabsf(distance-mImpostorDistance);
+ if (dist_diff/mImpostorDistance > 0.1f)
+ {
+ mNeedsImpostorUpdate = TRUE;
+ }
+ else
+ {
+ getSpatialExtents(ext[0], ext[1]);
+ if ((ext[1]-mImpostorExtents[1]).magVec() > 0.05f ||
+ (ext[0]-mImpostorExtents[0]).magVec() > 0.05f)
+ {
+ mNeedsImpostorUpdate = TRUE;
+ }
}
}
}
+
+ mDrawable->movePartition();
//force a move if sitting on an active object
if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
@@ -2613,7 +2772,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds
BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
BOOL render_name = visible_chat ||
- (isVisible() &&
+ (visible &&
((sRenderName == RENDER_NAME_ALWAYS) ||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
// If it's your own avatar, don't draw in mouselook, and don't
@@ -2996,10 +3155,9 @@ void LLVOAvatar::slamPosition()
// updateCharacter()
// called on both your avatar and other avatars
//------------------------------------------------------------------------
-void LLVOAvatar::updateCharacter(LLAgent &agent)
+BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
-
// update screen joint size
if (mScreenp)
{
@@ -3045,7 +3203,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
{
gAgent.setPositionAgent(getPositionAgent());
}
- return;
+ return FALSE;
}
@@ -3053,19 +3211,51 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
if (!mIsBuilt)
{
- return;
+ return FALSE;
}
+ BOOL visible = isVisible();
+
// For fading out the names above heads, only let the timer
// run if we're visible.
- if (mDrawable.notNull() && !mDrawable->isVisible())
+ if (mDrawable.notNull() && !visible)
{
mTimeVisible.reset();
}
- if (!mIsSelf && !isVisible())
+
+ //--------------------------------------------------------------------
+ // the rest should only be done occasionally for far away avatars
+ //--------------------------------------------------------------------
+
+ if (!mIsSelf && sUseImpostors && !mNeedsAnimUpdate)
{
- return;
+ F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
+ if (visible && mPixelArea <= impostor_area)
+ {
+ mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mPixelArea), 2, 8);
+
+ visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE;
+ }
+ else
+ {
+ mUpdatePeriod = 1;
+ }
+
+ if (!visible)
+ {
+ if (!mMotionController.isPaused())
+ {
+ mMotionController.pause();
+ mMotionController.updateMotion();
+ mMotionController.unpause();
+ }
+ else
+ {
+ mMotionController.updateMotion();
+ }
+ return FALSE;
+ }
}
// change animation time quanta based on avatar render load
@@ -3336,27 +3526,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
mRoot.setRotation(mDrawable->getRotation());
}
- //--------------------------------------------------------------------
- // the rest should only be done when close enough to see it
- //--------------------------------------------------------------------
-
-
- if (mPixelArea > 12.0f)
- throttle = FALSE;
- if (mPixelArea < 400.0f)
- {
- throttle = (LLDrawable::getCurrentFrame()+mID.mData[0])%2 != 0;
- }
-
- if ( !(mIsSitting && getParent()) &&
- (throttle ||
- (!isVisible() && (mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE))) )
- {
- mRoot.setWorldRotation( getRotation() );
- mRoot.updateWorldMatrixChildren();
- return;
- }
-
//-------------------------------------------------------------------------
// Update character motions
//-------------------------------------------------------------------------
@@ -3494,6 +3663,11 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
{
setDebugText(mDebugText);
}
+
+ //mesh vertices need to be reskinned
+ mNeedsSkin = TRUE;
+
+ return TRUE;
}
//-----------------------------------------------------------------------------
@@ -3524,7 +3698,7 @@ void LLVOAvatar::updateHeadOffset()
//------------------------------------------------------------------------
// updateVisibility()
//------------------------------------------------------------------------
-void LLVOAvatar::updateVisibility(BOOL force_invisible)
+void LLVOAvatar::updateVisibility()
{
BOOL visible = FALSE;
@@ -3536,7 +3710,7 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
{
visible = FALSE;
}
- else if (!force_invisible)
+ else
{
// calculate avatar distance wrt head
mDrawable->updateDistance(*gCamera);
@@ -3659,48 +3833,6 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible)
}
//------------------------------------------------------------------------
-// updateAllVisibility()
-//------------------------------------------------------------------------
-//static
-void LLVOAvatar::updateAllAvatarVisiblity()
-{
- LLVOAvatar::sNumVisibleAvatars = 0;
-
- F32 render_priority = (F32)LLVOAvatar::sMaxVisible;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* avatarp = (LLVOAvatar*) *iter;
- if (avatarp->isDead())
- {
- continue;
- }
- if (avatarp->isSelf())
- {
- avatarp->mRenderPriority = 1000.f;
- }
- else
- {
- avatarp->mRenderPriority = render_priority * 10.f; // 500 -> 10
- if (render_priority > 0.f)
- {
- render_priority -= 1.f;
- }
- }
- avatarp->updateVisibility(LLVOAvatar::sNumVisibleAvatars > LLVOAvatar::sMaxVisible);
-
- if (avatarp->mDrawable.isNull())
- {
- llwarns << "Avatar with no drawable" << llendl;
- }
- else if (avatarp->mDrawable->isVisible())
- {
- LLVOAvatar::sNumVisibleAvatars++;
- }
- }
-}
-
-//------------------------------------------------------------------------
// needsRenderBeam()
//------------------------------------------------------------------------
BOOL LLVOAvatar::needsRenderBeam()
@@ -3733,6 +3865,47 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
return num_indices;
}
+ if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
+ { //LOD changed or new mesh created, allocate new vertex buffer if needed
+ updateMeshData();
+ mDirtyMesh = FALSE;
+ mNeedsSkin = TRUE;
+ mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
+ }
+
+ if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) <= 0)
+ {
+ if (mNeedsSkin)
+ {
+ //generate animated mesh
+ mLowerBodyLOD.updateGeometry();
+ mUpperBodyLOD.updateGeometry();
+
+ if( isWearingWearableType( WT_SKIRT ) )
+ {
+ mSkirtLOD.updateGeometry();
+ }
+
+ if (!mIsSelf || gAgent.needsRenderHead())
+ {
+ mEyeLashLOD.updateGeometry();
+ mHeadLOD.updateGeometry();
+ mHairLOD.updateGeometry();
+ }
+ mNeedsSkin = FALSE;
+
+ LLVertexBuffer* vb = mDrawable->getFace(0)->mVertexBuffer;
+ if (vb)
+ {
+ vb->setBuffer(0);
+ }
+ }
+ }
+ else
+ {
+ mNeedsSkin = FALSE;
+ }
+
if (sDebugInvisible)
{
LLNameValue* firstname = getNVPair("FirstName");
@@ -3777,27 +3950,27 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
LLVector3 collide_point = slaved_pos;
collide_point.mV[VZ] -= foot_plane_normal.mV[VZ] * (dist_from_plane + COLLISION_TOLERANCE - FOOT_COLLIDE_FUDGE);
- glBegin(GL_LINES);
+ gGL.begin(GL_LINES);
{
F32 SQUARE_SIZE = 0.2f;
- glColor4f(1.f, 0.f, 0.f, 1.f);
+ gGL.color4f(1.f, 0.f, 0.f, 1.f);
- glVertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] + SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] + SQUARE_SIZE, collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] - SQUARE_SIZE, collide_point.mV[VY] - SQUARE_SIZE, collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX], collide_point.mV[VY], collide_point.mV[VZ]);
- glVertex3f(collide_point.mV[VX] + mFootPlane.mV[VX], collide_point.mV[VY] + mFootPlane.mV[VY], collide_point.mV[VZ] + mFootPlane.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX], collide_point.mV[VY], collide_point.mV[VZ]);
+ gGL.vertex3f(collide_point.mV[VX] + mFootPlane.mV[VX], collide_point.mV[VY] + mFootPlane.mV[VY], collide_point.mV[VZ] + mFootPlane.mV[VZ]);
- }glEnd();
+ }gGL.end();
}
//--------------------------------------------------------------------
// render all geomety attached to the skeleton
@@ -3823,41 +3996,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
num_indices += renderTransparent();
}
}
- /*else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER)
- {
- if (!mIsSelf || gAgent.needsRenderHead())
- {
- num_indices += mHeadLOD.render(mAdjustedPixelArea);
- }
- LLViewerJointMesh::sClothingInnerColor = mTexSkinColor->getColor() * 0.5f;
- LLViewerJointMesh::sClothingMaskImageName = mUpperMaskTexName;
- num_indices += mUpperBodyLOD.render(mAdjustedPixelArea);
- LLViewerJointMesh::sClothingMaskImageName = mLowerMaskTexName;
- num_indices += mLowerBodyLOD.render(mAdjustedPixelArea);
- LLViewerJointMesh::sClothingMaskImageName = 0;
- if( isWearingWearableType( WT_SKIRT ) )
- {
- glAlphaFunc(GL_GREATER,0.25f);
- num_indices += mSkirtLOD.render(mAdjustedPixelArea);
- glAlphaFunc(GL_GREATER,0.01f);
- }
-
- if (!mIsSelf || gAgent.needsRenderHead())
- {
- num_indices += mEyeLashLOD.render(mAdjustedPixelArea);
- num_indices += mHairLOD.render(mAdjustedPixelArea);
- }
- }
- else if (pass == AVATAR_RENDER_PASS_CLOTHING_OUTER)
- {
- LLViewerJointMesh::sClothingInnerColor = mTexSkinColor->getColor() * 0.5f;
- LLViewerJointMesh::sClothingMaskImageName = mUpperMaskTexName;
- num_indices += mUpperBodyLOD.render(mAdjustedPixelArea);
- LLViewerJointMesh::sClothingMaskImageName = mLowerMaskTexName;
- num_indices += mLowerBodyLOD.render(mAdjustedPixelArea);
- LLViewerJointMesh::sClothingMaskImageName = 0;
- }*/
-
+
LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
//llinfos << "Avatar render: " << render_timer.getElapsedTimeF32() << llendl;
@@ -3881,8 +4020,16 @@ U32 LLVOAvatar::renderTransparent()
if (!mIsSelf || gAgent.needsRenderHead())
{
+ if (LLPipeline::sImpostorRender)
+ {
+ glAlphaFunc(GL_GREATER, 0.5f);
+ }
num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass);
num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE);
+ if (LLPipeline::sImpostorRender)
+ {
+ glAlphaFunc(GL_GREATER, 0.01f);
+ }
}
return num_indices;
@@ -3935,9 +4082,17 @@ U32 LLVOAvatar::renderFootShadows()
return 0;
}
+ // Update the shadow, tractor, and text label geometry.
+ if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor())
+ {
+ updateShadowFaces();
+ mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
+ }
+
U32 foot_mask = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_TEXCOORD;
+ LLGLDepthTest test(GL_TRUE, GL_FALSE);
//render foot shadows
LLGLEnable blend(GL_BLEND);
mShadowImagep->bind();
@@ -3949,6 +4104,38 @@ U32 LLVOAvatar::renderFootShadows()
return num_indices;
}
+U32 LLVOAvatar::renderImpostor(LLColor4U color)
+{
+ if (!mImpostor.isComplete())
+ {
+ return 0;
+ }
+
+ LLVector3 pos(getRenderPosition()+mImpostorOffset);
+ LLVector3 left = gCamera->getLeftAxis()*mImpostorDim.mV[0];
+ LLVector3 up = gCamera->getUpAxis()*mImpostorDim.mV[1];
+
+ LLGLEnable test(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.f);
+
+ gGL.start();
+ gGL.color4ubv(color.mV);
+ mImpostor.bindTexture();
+ gGL.begin(GL_QUADS);
+ gGL.texCoord2f(0,0);
+ gGL.vertex3fv((pos+left-up).mV);
+ gGL.texCoord2f(1,0);
+ gGL.vertex3fv((pos-left-up).mV);
+ gGL.texCoord2f(1,1);
+ gGL.vertex3fv((pos-left+up).mV);
+ gGL.texCoord2f(0,1);
+ gGL.vertex3fv((pos+left+up).mV);
+ gGL.end();
+ gGL.stop();
+
+ return 6;
+}
+
//-----------------------------------------------------------------------------
// renderCollisionVolumes()
//-----------------------------------------------------------------------------
@@ -3965,7 +4152,6 @@ void LLVOAvatar::renderCollisionVolumes()
//------------------------------------------------------------------------
void LLVOAvatar::updateTextures(LLAgent &agent)
{
-// LLFastTimer ftm(LLFastTimer::FTM_TEMP5);
BOOL render_avatar = TRUE;
if (mIsDummy || gNoRender)
@@ -5423,38 +5609,23 @@ BOOL LLVOAvatar::isActive() const
void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- F32 max_scale = getMaxScale();
- F32 mid_scale = getMidScale();
- F32 min_scale = llmin( getScale().mV[VX], llmin( getScale().mV[VY], getScale().mV[VZ] ) );
- // IW: esitmate - when close to large objects, computing range based on distance from center is no good
- // to try to get a min distance from face, subtract min_scale/2 from the range.
- // This means we'll load too much detail sometimes, but that's better than not enough
- // I don't think there's a better way to do this without calculating distance per-poly
- F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec() - min_scale/2;
+ const LLVector3* ext = mDrawable->getSpatialExtents();
+ LLVector3 center = (ext[1] + ext[0]) * 0.5f;
+ LLVector3 size = (ext[1]-ext[0])*0.5f;
+
+ mPixelArea = LLPipeline::calcPixelArea(center, size, *gCamera);
+
+ F32 range = mDrawable->mDistanceWRTCamera;
if (range < 0.001f) // range == zero
{
mAppAngle = 180.f;
- mPixelArea = gCamera->getViewHeightInPixels() *
- gCamera->getViewHeightInPixels() *
- gCamera->getAspect();
}
else
{
- mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
-
- F32 pixels_per_meter = gCamera->getPixelMeterRatio() / range;
-
- mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale);
-// if( !mIsSelf )
-// {
-// llinfos << "range " << range << llendl;
-// llinfos << "pixels_per_meter " << pixels_per_meter << llendl;
-// llinfos << "scale " << max_scale << "x" << mid_scale << llendl;
-// llinfos << "pixel area " << mPixelArea << llendl;
-// }
+ F32 radius = size.magVec();
+ mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG;
}
// We always want to look good to ourselves
@@ -5567,10 +5738,11 @@ void LLVOAvatar::updateShadowFaces()
{
LLFace *face0p = mShadow0Facep;
LLFace *face1p = mShadow1Facep;
+
//
// render avatar shadows
//
- if (mInAir)
+ if (mInAir || mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD)
{
face0p->setSize(0, 0);
face1p->setSize(0, 0);
@@ -5583,7 +5755,7 @@ void LLVOAvatar::updateShadowFaces()
F32 cos_elev = sqrt(1 - cos_angle * cos_angle);
if (cos_angle < 0) cos_elev = -cos_elev;
sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
- LLVector3 sun_vec = gSky.mVOSkyp->getToSun();
+ LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
if (mShadowImagep->getHasGLTexture())
{
@@ -5771,7 +5943,14 @@ void LLVOAvatar::setParent(LLViewerObject* parent)
void LLVOAvatar::addChild(LLViewerObject *childp)
{
LLViewerObject::addChild(childp);
- attachObject(childp);
+ if (childp->mDrawable)
+ {
+ attachObject(childp);
+ }
+ else
+ {
+ mPendingAttachment.push_back(childp);
+ }
}
void LLVOAvatar::removeChild(LLViewerObject *childp)
@@ -5829,20 +6008,15 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object)
//-----------------------------------------------------------------------------
void LLVOAvatar::lazyAttach()
{
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ for (U32 i = 0; i < mPendingAttachment.size(); i++)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getAttachmentDirty())
+ if (mPendingAttachment[i]->mDrawable)
{
- attachment->lazyAttach();
- if (mIsSelf)
- {
- updateAttachmentVisibility(gAgent.getCameraMode());
- }
+ attachObject(mPendingAttachment[i]);
}
}
+
+ mPendingAttachment.clear();
}
void LLVOAvatar::resetHUDAttachments()
@@ -9159,253 +9333,6 @@ BOOL LLVOAvatarInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
return TRUE;
}
-void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base)
-{
- char filename[MAX_PATH]; /* Flawfinder: ignore */
-
- // reset animated morphs
- setVisualParamWeight("Blink_Left", 0.f);
- setVisualParamWeight("Blink_Right", 0.f);
- setVisualParamWeight("Hands_Relaxed", 1.f);
- setVisualParamWeight("Hands_Point", 0.f);
- setVisualParamWeight("Hands_Fist", 0.f);
- setVisualParamWeight("Hands_Relaxed_L", 0.f);
- setVisualParamWeight("Hands_Point_L", 0.f);
- setVisualParamWeight("Hands_Fist_L", 0.f);
- setVisualParamWeight("Hands_Relaxed_R", 0.f);
- setVisualParamWeight("Hands_Point_R", 0.f);
- setVisualParamWeight("Hands_Fist_R", 0.f);
- setVisualParamWeight("Hands_Salute_R", 0.f);
- setVisualParamWeight("Hands_Typing", 0.f);
- setVisualParamWeight("Hands_Peace_R", 0.f);
- setVisualParamWeight("Hands_Spread_R", 0.f);
- updateVisualParams();
-
- snprintf(filename, MAX_PATH, "%s\\%s_skeleton.xsf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write avatar file " << filename << llendl;
- return;
- }
- apr_file_printf(fp, "<SKELETON VERSION=\"1000\" NUMBONES=\"%d\">\n", sSkeletonInfo->getNumBones() - sSkeletonInfo->getNumCollisionVolumes());
- mRoot.writeCAL3D(fp);
- apr_file_printf(fp, "</SKELETON>\n");
- apr_file_close(fp);
-
- snprintf(filename, MAX_PATH, "%s\\%s_mesh_body.xmf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- //gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"avatar.cal").c_str()
- fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write avatar file " << filename << llendl;
- return;
- }
-
- BOOL has_skirt = isWearingWearableType(WT_SKIRT);
-
- apr_file_printf(fp, "<MESH VERSION=\"1000\" NUMSUBMESH=\"%d\">\n", has_skirt ? 8 : 7);
- mHairMesh0.writeCAL3D(fp, 5, this);
- mHeadMesh0.writeCAL3D(fp, 0, this);
- mEyeLashMesh0.writeCAL3D(fp, 0, this);
- mUpperBodyMesh0.writeCAL3D(fp, 1, this);
- mLowerBodyMesh0.writeCAL3D(fp, 2, this);
- mEyeBallLeftMesh0.writeCAL3D(fp, 3, this);
- mEyeBallRightMesh0.writeCAL3D(fp, 3, this);
- if (has_skirt)
- {
- mSkirtMesh0.writeCAL3D(fp, 4, this);
- }
- apr_file_printf(fp, "</MESH>\n");
- apr_file_close(fp);
-
- // write out material files
- LLPointer<LLImageTGA> tga_image = new LLImageTGA;
-
- for (S32 i = 0; i < (has_skirt ? BAKED_TEXTURE_COUNT : BAKED_TEXTURE_COUNT - 1); i++)
- {
- snprintf(filename, MAX_PATH, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), i); /* Flawfinder: ignore */
-
- LLViewerImage* viewer_imagep = mTEImages[sBakedTextureIndices[i]];
- if (!viewer_imagep->getHasGLTexture())
- {
- llinfos << "No image data available for " << filename << llendl;
- continue;
- }
- LLPointer<LLImageRaw> raw_image = new LLImageRaw;
- viewer_imagep->readBackRaw(-1, raw_image, false);
- BOOL success = tga_image->encode(raw_image);
- success = tga_image->save(filename);
- }
-
- // output image for hair
- snprintf(filename, MAX_PATH, "%s\\%s_material_tex_5.tga", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- LLViewerImage* viewer_imagep = mTEImages[TEX_HAIR];
- if (!viewer_imagep->getHasGLTexture())
- {
- llinfos << "No image data available for " << filename << llendl;
- }
- else
- {
- LLPointer<LLImageRaw> raw_image = new LLImageRaw;
- viewer_imagep->readBackRaw(-1, raw_image, false);
- BOOL success = tga_image->encode(raw_image);
- success = tga_image->save(filename);
- }
-
- // save out attachments
- snprintf(filename, MAX_PATH, "%s\\%s_mesh_attachments.xmf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write attachments file " << filename << llendl;
- return;
- }
-
- typedef std::multimap<LLUUID, LLMaterialExportInfo*>::iterator material_it_t;
- std::multimap<LLUUID, LLMaterialExportInfo*> material_map;
-
- S32 num_attachment_objects = 0;
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
- if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull() &&
- attached_object->getPCode() == LL_PCODE_VOLUME)
- {
- num_attachment_objects += attached_object->mDrawable->getNumFaces();
- for (U32 i = 0; i < attached_object->mChildList.size(); i++)
- {
- LLViewerObject* child_object = attached_object->mChildList[i];
- num_attachment_objects += child_object->mDrawable->getNumFaces();
- }
- }
- }
-
- apr_file_printf(fp, "<MESH VERSION=\"1000\" NUMSUBMESH=\"%d\">\n", num_attachment_objects);
-
- S32 material_index = 6;
- S32 texture_index = 6;
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
- if (attached_object && !attached_object->isDead() && attached_object->getPCode() == LL_PCODE_VOLUME)
- {
- LLVOVolume* attached_volume = (LLVOVolume*)attached_object;
- LLVector3 pos = attachment->getPosition();
- LLJoint* cur_joint = attachment->getParent();
- while (cur_joint)
- {
- pos += cur_joint->getSkinOffset();
- cur_joint = (LLViewerJoint*)cur_joint->getParent();
- }
- pos *= 100.f;
- S32 attached_joint_num = attachment->getParent()->mJointNum;
- LLQuaternion rot = attachment->getRotation();
- attached_volume->writeCAL3D(fp, path, file_base, attached_joint_num, pos, rot, material_index, texture_index, material_map);
- }
- }
- apr_file_printf(fp, "</MESH>\n");
- apr_file_close(fp);
-
- // now dump sample animation
- LLKeyframeMotion* walk_motion =
- getSex() == SEX_MALE ? (LLKeyframeMotion*)findMotion(ANIM_AGENT_WALK) : (LLKeyframeMotion*)findMotion(ANIM_AGENT_FEMALE_WALK);
- if (FALSE)//(walk_motion)
- {
- snprintf(filename, MAX_PATH, "%s\\%s_anim.xaf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write avatar animation file " << filename << llendl;
- return;
- }
-
- walk_motion->writeCAL3D(fp);
-
- apr_file_close(fp);
- }
-
- // finally, write out .cfg file
- snprintf(filename, MAX_PATH, "%s\\%s_avatar.cfg", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */
- fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write avatar config file " << filename << llendl;
- return;
- }
-
- // this version exports animation
- //apr_file_printf(fp, "#\n# cal3d model configuration file\n#\n# model: %s_avatar\n#\n\nscale=1.0\n\nskeleton=%s_skeleton.xsf\n\nanimation=%s_anim.xaf\n\n", file_base.c_str(), file_base.c_str(), file_base.c_str());
- apr_file_printf(fp, "#\n# cal3d model configuration file\n#\n# model: %s_avatar\n#\n\nscale=1.0\n\nskeleton=%s_skeleton.xsf\n\n", file_base.c_str(), file_base.c_str());
- apr_file_printf(fp, "mesh=%s_mesh_body.xmf\nmesh=%s_mesh_attachments.xmf\n", file_base.c_str(), file_base.c_str());
-
- for (S32 i = 0; i < material_index; i++)
- {
- apr_file_printf(fp, "material=%s_material_%d.xrf\n", file_base.c_str(), i);
- }
- apr_file_close(fp);
-
- for(S32 i = 0; i < 6; i++)
- {
- snprintf(filename, MAX_PATH, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), i); /* Flawfinder: ignore */
- apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write material definition file " << filename << llendl;
- return;
- }
-
- // for hair material, use hair color...otherwise use white for entire body
- LLColor4U material_color = (i == 5) ? mTexHairColor->getColor() : LLColor4U::white;
-
- apr_file_printf(fp, "<HEADER MAGIC=\"XRF\" VERSION=\"900\" />\n<MATERIAL NUMMAPS=\"1\">\n");
- apr_file_printf(fp, " <AMBIENT>%d %d %d %d</AMBIENT>\n", material_color.mV[VX], material_color.mV[VY], material_color.mV[VZ], material_color.mV[VW]);
- apr_file_printf(fp, " <DIFFUSE>%d %d %d %d</DIFFUSE>\n", material_color.mV[VX], material_color.mV[VY], material_color.mV[VZ], material_color.mV[VW]);
- apr_file_printf(fp, " <SPECULAR>0 0 0 0</SPECULAR>\n");
- apr_file_printf(fp, " <SHININESS>1.0</SHININESS>\n");
- apr_file_printf(fp, " <MAP>%s_material_tex_%d.tga</MAP>\n", file_base.c_str(), i);
- apr_file_printf(fp, "</MATERIAL>\n");
-
- apr_file_close(fp);
- }
-
- // write out material files
- for(material_it_t material_it = material_map.begin(); material_it != material_map.end(); ++material_it)
- {
- LLMaterialExportInfo* export_info = material_it->second;
-
- snprintf(filename, MAX_PATH, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), export_info->mMaterialIndex); /* Flawfinder: ignore */
- apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W);
- if (!fp)
- {
- llwarns << "Unable to write material definition file " << filename << llendl;
- return;
- }
-
- LLColor4U material_color = export_info->mColor;
-
- apr_file_printf(fp, "<HEADER MAGIC=\"XRF\" VERSION=\"900\" />\n<MATERIAL NUMMAPS=\"1\">\n");
- apr_file_printf(fp, " <AMBIENT>%d %d %d %d</AMBIENT>\n", material_color.mV[VX], material_color.mV[VY], material_color.mV[VZ], material_color.mV[VW]);
- apr_file_printf(fp, " <DIFFUSE>%d %d %d %d</DIFFUSE>\n", material_color.mV[VX], material_color.mV[VY], material_color.mV[VZ], material_color.mV[VW]);
- apr_file_printf(fp, " <SPECULAR>0 0 0 0</SPECULAR>\n");
- apr_file_printf(fp, " <SHININESS>1.0</SHININESS>\n");
- apr_file_printf(fp, " <MAP>%s_material_tex_%d.tga</MAP>\n", file_base.c_str(), export_info->mTextureIndex);
- apr_file_printf(fp, "</MATERIAL>\n");
-
- apr_file_close(fp);
- }
-
-
- std::for_each(material_map.begin(), material_map.end(), DeletePairedPointer());
- material_map.clear();
-}
-
// warning: order(N) not order(1)
S32 LLVOAvatar::getAttachmentCount()
{
@@ -9523,40 +9450,75 @@ BOOL LLVOAvatar::updateLOD()
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
updateMeshData();
mDirtyMesh = FALSE;
+ mNeedsSkin = TRUE;
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}
- if (facep->getPool()->getVertexShaderLevel() <= 0)
- {
- //generate animated mesh
- mLowerBodyLOD.updateGeometry();
- mUpperBodyLOD.updateGeometry();
- if( isWearingWearableType( WT_SKIRT ) )
- {
- mSkirtLOD.updateGeometry();
- }
+ return res;
+}
- if (!mIsSelf || gAgent.needsRenderHead())
+U32 LLVOAvatar::getPartitionType() const
+{ //avatars merely exist as drawables in the bridge partition
+ return LLViewerRegion::PARTITION_BRIDGE;
+}
+
+//static
+void LLVOAvatar::updateImpostors()
+{
+ for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
+ iter != LLCharacter::sInstances.end(); ++iter)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*) *iter;
+
+ if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor())
{
- mEyeLashLOD.updateGeometry();
- mHeadLOD.updateGeometry();
- mHairLOD.updateGeometry();
+ gPipeline.generateImpostor(avatar);
}
}
+}
- // Update the shadow, tractor, and text label geometry.
- if (mDrawable->isState(LLDrawable::REBUILD_SHADOW))
- {
- updateShadowFaces();
- mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
- }
+BOOL LLVOAvatar::isImpostor() const
+{
+ return (sUseImpostors && mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) ? TRUE : FALSE;
+}
- return res;
+
+BOOL LLVOAvatar::needsImpostorUpdate() const
+{
+ return mNeedsImpostorUpdate;
}
-U32 LLVOAvatar::getPartitionType() const
-{ //avatars merely exist as drawables in the bridge partition
- return LLPipeline::PARTITION_BRIDGE;
+const LLVector3& LLVOAvatar::getImpostorOffset() const
+{
+ return mImpostorOffset;
+}
+
+const LLVector2& LLVOAvatar::getImpostorDim() const
+{
+ return mImpostorDim;
+}
+
+void LLVOAvatar::setImpostorDim(const LLVector2& dim)
+{
+ mImpostorDim = dim;
+}
+
+void LLVOAvatar::cacheImpostorValues()
+{
+ getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance);
+}
+
+void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance)
+{
+ const LLVector3* ext = mDrawable->getSpatialExtents();
+ extents[0] = ext[0];
+ extents[1] = ext[1];
+
+ LLVector3 at = gCamera->getOrigin()-(getRenderPosition()+mImpostorOffset);
+ distance = at.normVec();
+ angle.mV[0] = acosf(at.mV[0]);
+ angle.mV[1] = acosf(at.mV[1]);
+ angle.mV[2] = acosf(at.mV[2]);
}