00001 
00032 
00033 
00034 
00035 #include "llviewerprecompiledheaders.h"
00036 
00037 #include "imageids.h"
00038 #include "llfasttimer.h"
00039 
00040 #include "llagent.h"
00041 #include "llapr.h"
00042 #include "llbox.h"
00043 #include "lldrawable.h"
00044 #include "lldrawpoolavatar.h"
00045 #include "lldrawpoolbump.h"
00046 #include "lldynamictexture.h"
00047 #include "llface.h"
00048 #include "llgldbg.h"
00049 #include "llglheaders.h"
00050 #include "lltexlayer.h"
00051 #include "llviewercamera.h"
00052 #include "llviewercontrol.h"
00053 #include "llviewerimagelist.h"
00054 #include "llviewerjointmesh.h"
00055 #include "llvoavatar.h"
00056 #include "llsky.h"
00057 #include "pipeline.h"
00058 #include "llglslshader.h"
00059 #include "llmath.h"
00060 #include "v4math.h"
00061 #include "m3math.h"
00062 #include "m4math.h"
00063 
00064 #if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS
00065 extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
00066 extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
00067 extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
00068 #endif
00069 extern BOOL gRenderForSelect;
00070 
00071 static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
00072 static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
00073                                                            LLVertexBuffer::MAP_NORMAL |
00074                                                            LLVertexBuffer::MAP_TEXCOORD;
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 LLSkinJoint::LLSkinJoint()
00087 {
00088         mJoint       = NULL;
00089 }
00090 
00091 
00092 
00093 
00094 LLSkinJoint::~LLSkinJoint()
00095 {
00096         mJoint = NULL;
00097 }
00098 
00099 
00100 
00101 
00102 
00103 BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
00104 {
00105         
00106         mJoint = joint;
00107         if ( !mJoint )
00108         {
00109                 llinfos << "Can't find joint" << llendl;
00110         }
00111 
00112         
00113         mRootToJointSkinOffset.clearVec();
00114 
00115         LLVector3 rootSkinOffset;
00116         while (joint)
00117         {
00118                 rootSkinOffset += joint->getSkinOffset();
00119                 joint = (LLViewerJoint*)joint->getParent();
00120         }
00121 
00122         mRootToJointSkinOffset = -rootSkinOffset;
00123         mRootToParentJointSkinOffset = mRootToJointSkinOffset;
00124         mRootToParentJointSkinOffset += mJoint->getSkinOffset();
00125 
00126         return TRUE;
00127 }
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 BOOL LLViewerJointMesh::sPipelineRender = FALSE;
00137 EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
00138 U32 LLViewerJointMesh::sClothingMaskImageName = 0;
00139 LLColor4 LLViewerJointMesh::sClothingInnerColor;
00140 
00141 
00142 
00143 
00144 LLViewerJointMesh::LLViewerJointMesh()
00145         :
00146         mTexture( NULL ),
00147         mLayerSet( NULL ),
00148         mTestImageName( 0 ),
00149         mIsTransparent(FALSE)
00150 {
00151 
00152         mColor[0] = 1.0f;
00153         mColor[1] = 1.0f;
00154         mColor[2] = 1.0f;
00155         mColor[3] = 1.0f;
00156         mShiny = 0.0f;
00157         mCullBackFaces = TRUE;
00158 
00159         mMesh = NULL;
00160 
00161         mNumSkinJoints = 0;
00162         mSkinJoints = NULL;
00163 
00164         mFace = NULL;
00165 
00166         mMeshID = 0;
00167         mUpdateXform = FALSE;
00168 
00169         mValid = FALSE;
00170 }
00171 
00172 
00173 
00174 
00175 
00176 
00177 LLViewerJointMesh::~LLViewerJointMesh()
00178 {
00179         mMesh = NULL;
00180         mTexture = NULL;
00181         freeSkinData();
00182 }
00183 
00184 
00185 
00186 
00187 
00188 BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
00189 {
00190         mSkinJoints = new LLSkinJoint[ numSkinJoints ];
00191         mNumSkinJoints = numSkinJoints;
00192         return TRUE;
00193 }
00194 
00195 
00196 
00197 
00198 S32 LLViewerJointMesh::getBoundJointsByIndex(S32 index, S32 &joint_a, S32& joint_b)
00199 {
00200         S32 num_joints = 0;
00201         if (mNumSkinJoints == 0)
00202         {
00203                 return num_joints;
00204         }
00205 
00206         joint_a = -1;
00207         joint_b = -1;
00208 
00209         LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
00210 
00211         if (index < reference_mesh->mJointRenderData.count())
00212         {
00213                 LLJointRenderData* render_datap = reference_mesh->mJointRenderData[index];
00214                 if (render_datap->mSkinJoint)
00215                 {
00216                         joint_a = render_datap->mSkinJoint->mJoint->mJointNum;
00217                 }
00218                 num_joints++;
00219         }
00220         if (index + 1 < reference_mesh->mJointRenderData.count())
00221         {
00222                 LLJointRenderData* render_datap = reference_mesh->mJointRenderData[index + 1];
00223                 if (render_datap->mSkinJoint)
00224                 {
00225                         joint_b = render_datap->mSkinJoint->mJoint->mJointNum;
00226 
00227                         if (joint_a == -1)
00228                         {
00229                                 joint_a = render_datap->mSkinJoint->mJoint->getParent()->mJointNum;
00230                         }
00231                 }
00232                 num_joints++;
00233         }
00234         return num_joints;
00235 }
00236 
00237 
00238 
00239 
00240 void LLViewerJointMesh::freeSkinData()
00241 {
00242         mNumSkinJoints = 0;
00243         delete [] mSkinJoints;
00244         mSkinJoints = NULL;
00245 }
00246 
00247 
00248 
00249 
00250 void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
00251 {
00252         *red   = mColor[0];
00253         *green = mColor[1];
00254         *blue  = mColor[2];
00255         *alpha = mColor[3];
00256 }
00257 
00258 
00259 
00260 
00261 void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
00262 {
00263         mColor[0] = red;
00264         mColor[1] = green;
00265         mColor[2] = blue;
00266         mColor[3] = alpha;
00267 }
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281 void LLViewerJointMesh::setTexture( LLViewerImage *texture )
00282 {
00283         mTexture = texture;
00284 
00285         
00286         if( texture )
00287         {
00288                 mLayerSet = NULL;
00289                 
00290                 
00291         }
00292 }
00293 
00294 
00295 
00296 
00297 
00298 void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
00299 {
00300         mLayerSet = layer_set;
00301         
00302         
00303         if( layer_set )
00304         {
00305                 mTexture = NULL;
00306         }
00307 }
00308 
00309 
00310 
00311 
00312 
00313 
00314 LLPolyMesh *LLViewerJointMesh::getMesh()
00315 {
00316         return mMesh;
00317 }
00318 
00319 
00320 
00321 
00322 void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
00323 {
00324         
00325         mMesh = mesh;
00326 
00327         
00328         freeSkinData();
00329 
00330         if ( mMesh == NULL )
00331         {
00332                 return;
00333         }
00334 
00335         
00336         setPosition( mMesh->getPosition() );
00337         setRotation( mMesh->getRotation() );
00338         setScale( mMesh->getScale() );
00339 
00340         
00341         if ( mMesh->hasWeights() && !mMesh->isLOD())
00342         {
00343                 U32 numJointNames = mMesh->getNumJointNames();
00344                 
00345                 allocateSkinData( numJointNames );
00346                 std::string *jointNames = mMesh->getJointNames();
00347 
00348                 U32 jn;
00349                 for (jn = 0; jn < numJointNames; jn++)
00350                 {
00351                         
00352                         LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
00353                         mSkinJoints[jn].setupSkinJoint( joint );
00354                 }
00355         }
00356 
00357         
00358         if (!mMesh->isLOD())
00359         {
00360                 setupJoint((LLViewerJoint*)getRoot());
00361         }
00362 
00363 
00364 }
00365 
00366 
00367 
00368 
00369 void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
00370 {
00371 
00372 
00373 
00374         U32 sj;
00375         for (sj=0; sj<mNumSkinJoints; sj++)
00376         {
00377                 LLSkinJoint &js = mSkinJoints[sj];
00378 
00379                 if (js.mJoint != current_joint)
00380                 {
00381                         continue;
00382                 }
00383 
00384                 
00385 
00386                 
00387                 if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix())
00388                 {
00389                         
00390                         LLViewerJoint* jointp = js.mJoint;
00391                         mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
00392 
00393 
00394                 }
00395                 
00396                 else
00397                 {
00398                         mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL));
00399 
00400 
00401                         mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js));
00402 
00403 
00404                 }
00405         }
00406 
00407         
00408         for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
00409                  iter != current_joint->mChildren.end(); ++iter)
00410         {
00411                 LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
00412                 setupJoint(child_joint);
00413         }
00414 }
00415 
00416 const S32 NUM_AXES = 3;
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 static LLMatrix4        gJointMatUnaligned[32];
00425 static LLMatrix3        gJointRotUnaligned[32];
00426 static LLVector4        gJointPivot[32];
00427 
00428 
00429 
00430 
00431 void LLViewerJointMesh::uploadJointMatrices()
00432 {
00433         S32 joint_num;
00434         LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
00435         LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
00436         BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
00437 
00438         
00439         for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00440         {
00441                 LLMatrix4 joint_mat = *reference_mesh->mJointRenderData[joint_num]->mWorldMatrix;
00442 
00443                 if (hardware_skinning)
00444                 {
00445                         joint_mat *= LLDrawPoolAvatar::getModelView();
00446                 }
00447                 gJointMatUnaligned[joint_num] = joint_mat;
00448                 gJointRotUnaligned[joint_num] = joint_mat.getMat3();
00449         }
00450 
00451         BOOL last_pivot_uploaded = FALSE;
00452         S32 j = 0;
00453 
00454         
00455         for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00456         {
00457                 LLSkinJoint *sj = reference_mesh->mJointRenderData[joint_num]->mSkinJoint;
00458                 if (sj)
00459                 {
00460                         if (!last_pivot_uploaded)
00461                         {
00462                                 LLVector4 parent_pivot(sj->mRootToParentJointSkinOffset);
00463                                 parent_pivot.mV[VW] = 0.f;
00464                                 gJointPivot[j++] = parent_pivot;
00465                         }
00466 
00467                         LLVector4 child_pivot(sj->mRootToJointSkinOffset);
00468                         child_pivot.mV[VW] = 0.f;
00469 
00470                         gJointPivot[j++] = child_pivot;
00471 
00472                         last_pivot_uploaded = TRUE;
00473                 }
00474                 else
00475                 {
00476                         last_pivot_uploaded = FALSE;
00477                 }
00478         }
00479 
00480         
00481         for (S32 i = 0; i < j; i++)
00482         {
00483                 LLVector3 pivot;
00484                 pivot = LLVector3(gJointPivot[i]);
00485                 pivot = pivot * gJointRotUnaligned[i];
00486                 gJointMatUnaligned[i].translate(pivot);
00487         }
00488 
00489         
00490         if (hardware_skinning)
00491         {
00492                 GLfloat mat[45*4];
00493                 memset(mat, 0, sizeof(GLfloat)*45*4);
00494 
00495                 for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00496                 {
00497                         gJointMatUnaligned[joint_num].transpose();
00498 
00499                         for (S32 axis = 0; axis < NUM_AXES; axis++)
00500                         {
00501                                 F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis];
00502                                 
00503                                 U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
00504                                 memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
00505                                 
00506                                 
00507                         }
00508                 }
00509                 glUniform4fvARB(gAvatarMatrixParam, 45, mat);
00510         }
00511 }
00512 
00513 
00514 
00515 
00516 void LLViewerJointMesh::drawBone()
00517 {
00518 }
00519 
00520 
00521 
00522 
00523 BOOL LLViewerJointMesh::isTransparent()
00524 {
00525         return mIsTransparent;
00526 }
00527 
00528 
00529 
00530 
00531 
00532 
00533 int compare_int(const void *a, const void *b)
00534 {
00535         if (*(U32*)a < *(U32*)b)
00536         {
00537                 return -1;
00538         }
00539         else if (*(U32*)a > *(U32*)b)
00540         {
00541                 return 1;
00542         }
00543         else return 0;
00544 }
00545 
00546 void llDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices)
00547 {
00548         if (end-start+1 > (U32) gGLManager.mGLMaxVertexRange ||
00549                 count > gGLManager.mGLMaxIndexRange)
00550         {
00551                 glDrawElements(mode,count,type,indices);
00552         }
00553         else
00554         {
00555                 glDrawRangeElements(mode,start,end,count,type,indices);
00556         }
00557 }
00558 
00559 
00560 
00561 
00562 U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
00563 {
00564         if (!mValid || !mMesh || !mFace || !mVisible || 
00565                 mFace->mVertexBuffer.isNull() ||
00566                 mMesh->getNumFaces() == 0) 
00567         {
00568                 return 0;
00569         }
00570 
00571         U32 triangle_count = 0;
00572 
00573         stop_glerror();
00574         
00575         
00576         
00577         
00578         if (!gRenderForSelect)
00579         {
00580                 if ((mFace->getPool()->getVertexShaderLevel() > 0))
00581                 {
00582                         glColor4f(0,0,0,1);
00583                         
00584                         if (gMaterialIndex > 0)
00585                         {
00586                                 glVertexAttrib4fvARB(gMaterialIndex, mColor.mV);
00587                         }
00588                         
00589                         if (mShiny && gSpecularIndex > 0)
00590                         {
00591                                 glVertexAttrib4fARB(gSpecularIndex, 1,1,1,1);
00592                         }
00593                 }
00594                 else
00595                 {
00596                         glColor4fv(mColor.mV);
00597                 }
00598         }
00599 
00600         stop_glerror();
00601         
00602         LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
00603 
00604         LLGLEnable texture_2d((gRenderForSelect && isTransparent()) ? GL_TEXTURE_2D : 0);
00605         
00606         
00607         
00608         
00609         llassert( !(mTexture.notNull() && mLayerSet) );  
00610 
00611         if (mTestImageName)
00612         {
00613                 LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D ); 
00614 
00615                 if (mIsTransparent)
00616                 {
00617                         glColor4f(1.f, 1.f, 1.f, 1.f);
00618                 }
00619                 else
00620                 {
00621                         glColor4f(0.7f, 0.6f, 0.3f, 1.f);
00622                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00623                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_INTERPOLATE_ARB);
00624 
00625                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00626                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00627 
00628                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_TEXTURE);
00629                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00630                         
00631                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB,           GL_TEXTURE);
00632                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB,          GL_ONE_MINUS_SRC_ALPHA);
00633                 }
00634         }
00635         else if( mLayerSet )
00636         {
00637                 if(     mLayerSet->hasComposite() )
00638                 {
00639                         mLayerSet->getComposite()->bindTexture();
00640                 }
00641                 else
00642                 {
00643                         llwarns << "Layerset without composite" << llendl;
00644                         gImageList.getImage(IMG_DEFAULT)->bind();
00645                 }
00646         }
00647         else
00648         if ( mTexture.notNull() )
00649         {
00650                 mTexture->bind();
00651                 if (!mTexture->getClampS()) {
00652                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00653                 }
00654                 if (!mTexture->getClampT()) {
00655                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00656                 }
00657         }
00658         else
00659         {
00660                 gImageList.getImage(IMG_DEFAULT_AVATAR)->bind();
00661         }
00662         
00663         LLGLDisable tex(gRenderForSelect && !isTransparent() ? GL_TEXTURE_2D : 0);
00664 
00665         if (gRenderForSelect)
00666         {
00667                 if (isTransparent())
00668                 {
00669                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00670                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_REPLACE);
00671                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_MODULATE);
00672 
00673                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00674                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00675 
00676                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_TEXTURE);  
00677                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00678                 }
00679         }
00680         else
00681         {
00682                 
00683                 
00684                 
00685                 
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00739 
00740 
00741 
00742 
00743 
00744 
00745 
00746 
00747 
00748 
00749 
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757         }
00758 
00759         mFace->mVertexBuffer->setBuffer(sRenderMask);
00760 
00761         U32 start = mMesh->mFaceVertexOffset;
00762         U32 end = start + mMesh->mFaceVertexCount - 1;
00763         U32 count = mMesh->mFaceIndexCount;
00764         U32* indicesp = ((U32*) mFace->mVertexBuffer->getIndicesPointer()) + mMesh->mFaceIndexOffset;
00765 
00766         if (mMesh->hasWeights())
00767         {
00768                 if ((mFace->getPool()->getVertexShaderLevel() > 0))
00769                 {
00770                         if (first_pass)
00771                         {
00772                                 uploadJointMatrices();
00773                         }
00774                         llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
00775                 }
00776                 else
00777                 {
00778                         llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
00779                 }
00780         }
00781         else
00782         {
00783                 glPushMatrix();
00784                 LLMatrix4 jointToWorld = getWorldMatrix();
00785                 glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
00786                 llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp);
00787                 glPopMatrix();
00788         }
00789 
00790         triangle_count += mMesh->mFaceIndexCount;
00791         
00792         if (mTestImageName)
00793         {
00794                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00795         }
00796 
00797         
00798 
00799 
00800 
00801 
00802 
00803 
00804 
00805 
00806 
00807 
00808 
00809 
00810 
00811 
00812         if (mTexture.notNull()) {
00813                 if (!mTexture->getClampS()) {
00814                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00815                 }
00816                 if (!mTexture->getClampT()) {
00817                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00818                 }
00819         }
00820 
00821         return triangle_count;
00822 }
00823 
00824 
00825 
00826 
00827 void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
00828 {
00829         
00830         if (mMesh && mValid)
00831         {
00832                 mMesh->mFaceVertexOffset = num_vertices;
00833                 mMesh->mFaceVertexCount = mMesh->getNumVertices();
00834                 mMesh->mFaceIndexOffset = num_indices;
00835                 mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
00836 
00837                 mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount;
00838 
00839                 num_vertices += mMesh->getNumVertices();
00840                 num_indices += mMesh->mFaceIndexCount;
00841         }
00842 }
00843 
00844 
00845 
00846 
00847 void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
00848 {
00849         U32 i;
00850         
00851         mFace = face;
00852 
00853         LLStrider<LLVector3> verticesp;
00854         LLStrider<LLVector3> normalsp;
00855         LLStrider<LLVector3> binormalsp;
00856         LLStrider<LLVector2> tex_coordsp;
00857         LLStrider<F32>           vertex_weightsp;
00858         LLStrider<LLVector4> clothing_weightsp;
00859         LLStrider<U32> indicesp;
00860 
00861         
00862         if (mMesh && mValid)
00863         {
00864                 if (mMesh->getNumVertices())
00865                 {
00866                         S32 index = face->getGeometryAvatar(verticesp, normalsp, binormalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
00867                         face->mVertexBuffer->getIndexStrider(indicesp);
00868 
00869                         if (-1 == index)
00870                         {
00871                                 return;
00872                         }
00873 
00874                         for (i = 0; i < mMesh->getNumVertices(); i++)
00875                         {
00876                                 verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i);
00877                                 tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i);
00878                                 normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i);
00879                                 binormalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getBinormals() + i);
00880                                 vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i);
00881                                 if (damp_wind)
00882                                 {
00883                                         clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0);
00884                                 }
00885                                 else
00886                                 {
00887                                         clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i));
00888                                 }
00889                         }
00890 
00891                         for (S32 i = 0; i < mMesh->getNumFaces(); i++)
00892                         {
00893                                 for (U32 j = 0; j < 3; j++)
00894                                 {
00895                                         U32 k = i*3+j+mMesh->mFaceIndexOffset;
00896                                         indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset;
00897                                 }
00898                         }
00899                 }
00900         }
00901 }
00902 
00903 
00904 
00905 
00906 BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate)
00907 {
00908         BOOL valid = mValid;
00909         setValid(activate, TRUE);
00910         return (valid != activate);
00911 }
00912 
00913 
00914 void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
00915 {
00916         LLStrider<LLVector3> o_vertices;
00917         LLStrider<LLVector3> o_normals;
00918 
00919         
00920         LLVertexBuffer *buffer = mFace->mVertexBuffer;
00921         buffer->getVertexStrider(o_vertices,  0);
00922         buffer->getNormalStrider(o_normals,   0);
00923 
00924         F32 last_weight = F32_MAX;
00925         LLMatrix4 gBlendMat;
00926         LLMatrix3 gBlendRotMat;
00927 
00928         const F32* weights = mMesh->getWeights();
00929         const LLVector3* coords = mMesh->getCoords();
00930         const LLVector3* normals = mMesh->getNormals();
00931         for (U32 index = 0; index < mMesh->getNumVertices(); index++)
00932         {
00933                 U32 bidx = index + mMesh->mFaceVertexOffset;
00934                 
00935                 
00936                 F32 w = weights[index]; 
00937                 
00938                 
00939                 
00940                 
00941                 if (w == last_weight)
00942                 {
00943                         o_vertices[bidx] = coords[index] * gBlendMat;
00944                         o_normals[bidx] = normals[index] * gBlendRotMat;
00945                         continue;
00946                 }
00947                 
00948                 last_weight = w;
00949 
00950                 S32 joint = llfloor(w);
00951                 w -= joint;
00952                 
00953                 
00954                 if (w == 1.0f)
00955                 {
00956                         gBlendMat = gJointMatUnaligned[joint+1];
00957                         o_vertices[bidx] = coords[index] * gBlendMat;
00958                         gBlendRotMat = gJointRotUnaligned[joint+1];
00959                         o_normals[bidx] = normals[index] * gBlendRotMat;
00960                         continue;
00961                 }
00962                 
00963                 
00964                 
00965                 
00966                 LLMatrix4 &m0 = gJointMatUnaligned[joint+1];
00967                 LLMatrix4 &m1 = gJointMatUnaligned[joint+0];
00968                 
00969                 gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
00970                 gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
00971                 gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
00972 
00973                 gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
00974                 gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
00975                 gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
00976 
00977                 gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
00978                 gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
00979                 gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
00980 
00981                 gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
00982                 gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
00983                 gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
00984 
00985                 o_vertices[bidx] = coords[index] * gBlendMat;
00986                 
00987                 LLMatrix3 &n0 = gJointRotUnaligned[joint+1];
00988                 LLMatrix3 &n1 = gJointRotUnaligned[joint+0];
00989                 
00990                 gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
00991                 gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
00992                 gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
00993 
00994                 gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
00995                 gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
00996                 gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
00997 
00998                 gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
00999                 gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
01000                 gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
01001                 
01002                 o_normals[bidx] = normals[index] * gBlendRotMat;
01003         }
01004 }
01005 
01006 const U32 UPDATE_GEOMETRY_CALL_MASK                     = 0x1FFF; 
01007 const U32 UPDATE_GEOMETRY_CALL_OVERFLOW         = ~UPDATE_GEOMETRY_CALL_MASK;
01008 static bool sUpdateGeometryCallPointer          = false;
01009 static F64 sUpdateGeometryGlobalTime            = 0.0 ;
01010 static F64 sUpdateGeometryElapsedTime           = 0.0 ;
01011 static F64 sUpdateGeometryElapsedTimeOff        = 0.0 ;
01012 static F64 sUpdateGeometryElapsedTimeOn         = 0.0 ;
01013 static F64 sUpdateGeometryRunAvgOff[10];
01014 static F64 sUpdateGeometryRunAvgOn[10];
01015 static U32 sUpdateGeometryRunCount                      = 0 ;
01016 static U32 sUpdateGeometryCalls                         = 0 ;
01017 static U32 sUpdateGeometryLastProcessor         = 0 ;
01018 void (*LLViewerJointMesh::sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh);
01019 
01020 void LLViewerJointMesh::updateGeometry()
01021 {
01022         extern BOOL gVectorizePerfTest;
01023         extern U32      gVectorizeProcessor;
01024 
01025         if (!(mValid
01026                   && mMesh
01027                   && mFace
01028                   && mMesh->hasWeights()
01029                   && mFace->mVertexBuffer.notNull()
01030                   && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0))
01031         {
01032                 return;
01033         }
01034 
01035         if (!gVectorizePerfTest)
01036         {
01037                 
01038                 
01039                 if(sUpdateGeometryFunc == updateGeometryOriginal)
01040                         uploadJointMatrices();
01041                 sUpdateGeometryFunc(mFace, mMesh);
01042         }
01043         else
01044         {
01045                 
01046                 
01047                 LLTimer ug_timer ;
01048                 
01049                 if (sUpdateGeometryCallPointer)
01050                 {
01051                         if(sUpdateGeometryFunc == updateGeometryOriginal)
01052                                 uploadJointMatrices();
01053                         
01054                         sUpdateGeometryFunc(mFace, mMesh);
01055                 }
01056                 else
01057                 {
01058                         uploadJointMatrices();
01059                         updateGeometryOriginal(mFace, mMesh);
01060                 }
01061         
01062                 sUpdateGeometryElapsedTime += ug_timer.getElapsedTimeF64();
01063                 ++sUpdateGeometryCalls;
01064                 if(0 != (sUpdateGeometryCalls & UPDATE_GEOMETRY_CALL_OVERFLOW))
01065                 {
01066                         F64 time_since_app_start = ug_timer.getElapsedSeconds();
01067                         if(sUpdateGeometryGlobalTime == 0.0 
01068                                 || sUpdateGeometryLastProcessor != gVectorizeProcessor)
01069                         {
01070                                 sUpdateGeometryGlobalTime               = time_since_app_start;
01071                                 sUpdateGeometryElapsedTime              = 0;
01072                                 sUpdateGeometryCalls                    = 0;
01073                                 sUpdateGeometryRunCount                 = 0;
01074                                 sUpdateGeometryLastProcessor    = gVectorizeProcessor;
01075                                 sUpdateGeometryCallPointer              = false;
01076                                 return;
01077                         }
01078                         F64 percent_time_in_function = 
01079                                 ( sUpdateGeometryElapsedTime * 100.0 ) / ( time_since_app_start - sUpdateGeometryGlobalTime ) ;
01080                         sUpdateGeometryGlobalTime = time_since_app_start;
01081                         if (!sUpdateGeometryCallPointer)
01082                         {
01083                                 
01084                                 sUpdateGeometryCallPointer = true;
01085                                 llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
01086                                         << "vectorize off " << percent_time_in_function
01087                                         << "% of time with "
01088                                         << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
01089                                         << " seconds per call "
01090                                         << llendl;
01091                                 sUpdateGeometryRunAvgOff[sUpdateGeometryRunCount] = percent_time_in_function;
01092                                 sUpdateGeometryElapsedTimeOff += sUpdateGeometryElapsedTime;
01093                                 sUpdateGeometryCalls = 0;
01094                         }
01095                         else
01096                         {
01097                                 
01098                                 sUpdateGeometryCallPointer = false;
01099                                 llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
01100                                         << "VEC on " << percent_time_in_function
01101                                         << "% of time with "
01102                                         << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
01103                                         << " seconds per call "
01104                                         << llendl;
01105                                 sUpdateGeometryRunAvgOn[sUpdateGeometryRunCount] = percent_time_in_function ;
01106                                 sUpdateGeometryElapsedTimeOn += sUpdateGeometryElapsedTime;
01107 
01108                                 sUpdateGeometryCalls = 0;
01109                                 sUpdateGeometryRunCount++;
01110                                 F64 a = 0.0, b = 0.0;
01111                                 for(U32 i = 0; i<sUpdateGeometryRunCount; i++)
01112                                 {
01113                                         a += sUpdateGeometryRunAvgOff[i];
01114                                         b += sUpdateGeometryRunAvgOn[i];
01115                                 }
01116                                 a /= sUpdateGeometryRunCount;
01117                                 b /= sUpdateGeometryRunCount;
01118                                 F64 perf_boost = ( sUpdateGeometryElapsedTimeOff - sUpdateGeometryElapsedTimeOn ) / sUpdateGeometryElapsedTimeOn;
01119                                 llinfos << "run averages (" << (F64)sUpdateGeometryRunCount
01120                                         << "/10) vectorize off " << a
01121                                         << "% : vectorize type " << gVectorizeProcessor
01122                                         << " " << b
01123                                         << "% : performance boost " 
01124                                         << perf_boost * 100.0
01125                                         << "%"
01126                                         << llendl ;
01127                                 if(sUpdateGeometryRunCount == 10)
01128                                 {
01129                                         
01130                                         
01131                                         sUpdateGeometryGlobalTime = 0.0;
01132 
01133                                         
01134                                         
01135                                         gVectorizePerfTest = FALSE;
01136                                         gSavedSettings.setBOOL("VectorizePerfTest", FALSE);
01137 
01138                                         if (perf_boost > 0.0)
01139                                         {
01140                                                 llinfos << "Vectorization improves avatar skinning performance, "
01141                                                         << "keeping on for future runs."
01142                                                         << llendl;
01143                                                 gSavedSettings.setBOOL("VectorizeSkin", TRUE);
01144                                         }
01145                                         else
01146                                         {
01147                                                 
01148                                                 llinfos << "Vectorization decreases avatar skinning performance, "
01149                                                         << "switching back to original code."
01150                                                         << llendl;
01151 
01152                                                 gSavedSettings.setBOOL("VectorizeSkin", FALSE);
01153                                         }
01154                                 }
01155                         }
01156                         sUpdateGeometryElapsedTime = 0.0f;
01157                 }
01158         }
01159 }
01160 
01161 void LLViewerJointMesh::dump()
01162 {
01163         if (mValid)
01164         {
01165                 llinfos << "Usable LOD " << mName << llendl;
01166         }
01167 }
01168 
01169 void LLViewerJointMesh::writeCAL3D(apr_file_t* fp, S32 material_num, LLCharacter* characterp)
01170 {
01171         apr_file_printf(fp, "\t<SUBMESH NUMVERTICES=\"%d\" NUMFACES=\"%d\" MATERIAL=\"%d\" NUMLODSTEPS=\"0\" NUMSPRINGS=\"0\" NUMTEXCOORDS=\"1\">\n", mMesh->getNumVertices(), mMesh->getNumFaces(), material_num);
01172 
01173         const LLVector3* mesh_coords = mMesh->getCoords();
01174         const LLVector3* mesh_normals = mMesh->getNormals();
01175         const LLVector2* mesh_uvs = mMesh->getTexCoords();
01176         const F32* mesh_weights = mMesh->getWeights();
01177         LLVector3 mesh_offset;
01178         LLVector3 scale(1.f, 1.f, 1.f);
01179         S32 joint_a = -1;
01180         S32 joint_b = -1;
01181         S32 num_bound_joints = 0;
01182         
01183         if(!mMesh->hasWeights())
01184         {
01185                 num_bound_joints = 1;
01186                 LLJoint* cur_joint = this;
01187                 while(cur_joint)
01188                 {
01189                         if (cur_joint->mJointNum != -1 && joint_a == -1)
01190                         {
01191                                 joint_a = cur_joint->mJointNum;
01192                         }
01193                         mesh_offset += cur_joint->getSkinOffset();
01194                         cur_joint = cur_joint->getParent();
01195                 }
01196         }
01197 
01198         for (S32 i = 0; i < (S32)mMesh->getNumVertices(); i++)
01199         {
01200                 LLVector3 coord = mesh_coords[i];
01201 
01202                 if (mMesh->hasWeights())
01203                 {
01204                         
01205                         num_bound_joints = getBoundJointsByIndex(llfloor(mesh_weights[i]), joint_a, joint_b);
01206                         LLJoint* first_joint = characterp->getCharacterJoint(joint_a);
01207                         LLJoint* second_joint = characterp->getCharacterJoint(joint_b);
01208 
01209                         LLVector3 first_joint_offset;
01210                         LLJoint* cur_joint = first_joint;
01211                         while(cur_joint)
01212                         {
01213                                 first_joint_offset += cur_joint->getSkinOffset();
01214                                 cur_joint = cur_joint->getParent();
01215                         }
01216 
01217                         LLVector3 second_joint_offset;
01218                         cur_joint = second_joint;
01219                         while(cur_joint)
01220                         {
01221                                 second_joint_offset += cur_joint->getSkinOffset();
01222                                 cur_joint = cur_joint->getParent();
01223                         }
01224 
01225                         LLVector3 first_coord = coord - first_joint_offset;
01226                         first_coord.scaleVec(first_joint->getScale());
01227                         LLVector3 second_coord = coord - second_joint_offset;
01228                         if (second_joint)
01229                         {
01230                                 second_coord.scaleVec(second_joint->getScale());
01231                         }
01232                         
01233                         coord = lerp(first_joint_offset + first_coord, second_joint_offset + second_coord, fmodf(mesh_weights[i], 1.f));
01234                 }
01235 
01236                 
01237                 coord += mesh_offset;
01238                 coord *= 100.f;
01239 
01240                 apr_file_printf(fp, "           <VERTEX ID=\"%d\" NUMINFLUENCES=\"%d\">\n", i, num_bound_joints);
01241                 apr_file_printf(fp, "                   <POS>%.4f %.4f %.4f</POS>\n", coord.mV[VX], coord.mV[VY], coord.mV[VZ]);
01242                 apr_file_printf(fp, "                   <NORM>%.6f %.6f %.6f</NORM>\n", mesh_normals[i].mV[VX], mesh_normals[i].mV[VY], mesh_normals[i].mV[VZ]);
01243                 apr_file_printf(fp, "                   <TEXCOORD>%.6f %.6f</TEXCOORD>\n", mesh_uvs[i].mV[VX], 1.f - mesh_uvs[i].mV[VY]);
01244                 if (num_bound_joints >= 1)
01245                 {
01246                         apr_file_printf(fp, "                   <INFLUENCE ID=\"%d\">%.2f</INFLUENCE>\n", joint_a + 1, 1.f - fmod(mesh_weights[i], 1.f));
01247                 }
01248                 if (num_bound_joints == 2)
01249                 {
01250                         apr_file_printf(fp, "                   <INFLUENCE ID=\"%d\">%.2f</INFLUENCE>\n", joint_b + 1, fmod(mesh_weights[i], 1.f));
01251                 }
01252                 apr_file_printf(fp, "           </VERTEX>\n");
01253         }
01254 
01255         LLPolyFace* mesh_faces = mMesh->getFaces();
01256         for (S32 i = 0; i < mMesh->getNumFaces(); i++)
01257         {
01258                 apr_file_printf(fp, "           <FACE VERTEXID=\"%d %d %d\" />\n", mesh_faces[i][0], mesh_faces[i][1], mesh_faces[i][2]);
01259         }
01260         
01261         apr_file_printf(fp, "   </SUBMESH>\n");
01262 }
01263 
01264