llviewerjointmesh.cpp

Go to the documentation of this file.
00001 
00032 //-----------------------------------------------------------------------------
00033 // Header Files
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 // LLViewerJointMesh::LLSkinJoint
00080 //-----------------------------------------------------------------------------
00081 //-----------------------------------------------------------------------------
00082 
00083 //-----------------------------------------------------------------------------
00084 // LLSkinJoint
00085 //-----------------------------------------------------------------------------
00086 LLSkinJoint::LLSkinJoint()
00087 {
00088         mJoint       = NULL;
00089 }
00090 
00091 //-----------------------------------------------------------------------------
00092 // ~LLSkinJoint
00093 //-----------------------------------------------------------------------------
00094 LLSkinJoint::~LLSkinJoint()
00095 {
00096         mJoint = NULL;
00097 }
00098 
00099 
00100 //-----------------------------------------------------------------------------
00101 // LLSkinJoint::setupSkinJoint()
00102 //-----------------------------------------------------------------------------
00103 BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
00104 {
00105         // find the named joint
00106         mJoint = joint;
00107         if ( !mJoint )
00108         {
00109                 llinfos << "Can't find joint" << llendl;
00110         }
00111 
00112         // compute the inverse root skin matrix
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 // LLViewerJointMesh
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 // LLViewerJointMesh()
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 // ~LLViewerJointMesh()
00175 // Class Destructor
00176 //-----------------------------------------------------------------------------
00177 LLViewerJointMesh::~LLViewerJointMesh()
00178 {
00179         mMesh = NULL;
00180         mTexture = NULL;
00181         freeSkinData();
00182 }
00183 
00184 
00185 //-----------------------------------------------------------------------------
00186 // LLViewerJointMesh::allocateSkinData()
00187 //-----------------------------------------------------------------------------
00188 BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
00189 {
00190         mSkinJoints = new LLSkinJoint[ numSkinJoints ];
00191         mNumSkinJoints = numSkinJoints;
00192         return TRUE;
00193 }
00194 
00195 //-----------------------------------------------------------------------------
00196 // getSkinJointByIndex()
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 // LLViewerJointMesh::freeSkinData()
00239 //-----------------------------------------------------------------------------
00240 void LLViewerJointMesh::freeSkinData()
00241 {
00242         mNumSkinJoints = 0;
00243         delete [] mSkinJoints;
00244         mSkinJoints = NULL;
00245 }
00246 
00247 //--------------------------------------------------------------------
00248 // LLViewerJointMesh::getColor()
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 // LLViewerJointMesh::setColor()
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 // LLViewerJointMesh::getTexture()
00272 //--------------------------------------------------------------------
00273 //LLViewerImage *LLViewerJointMesh::getTexture()
00274 //{
00275 //      return mTexture;
00276 //}
00277 
00278 //--------------------------------------------------------------------
00279 // LLViewerJointMesh::setTexture()
00280 //--------------------------------------------------------------------
00281 void LLViewerJointMesh::setTexture( LLViewerImage *texture )
00282 {
00283         mTexture = texture;
00284 
00285         // texture and dynamic_texture are mutually exclusive
00286         if( texture )
00287         {
00288                 mLayerSet = NULL;
00289                 //texture->bindTexture(0);
00290                 //texture->setClamp(TRUE, TRUE);
00291         }
00292 }
00293 
00294 //--------------------------------------------------------------------
00295 // LLViewerJointMesh::setLayerSet()
00296 // Sets the shape texture (takes precedence over normal texture)
00297 //--------------------------------------------------------------------
00298 void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
00299 {
00300         mLayerSet = layer_set;
00301         
00302         // texture and dynamic_texture are mutually exclusive
00303         if( layer_set )
00304         {
00305                 mTexture = NULL;
00306         }
00307 }
00308 
00309 
00310 
00311 //--------------------------------------------------------------------
00312 // LLViewerJointMesh::getMesh()
00313 //--------------------------------------------------------------------
00314 LLPolyMesh *LLViewerJointMesh::getMesh()
00315 {
00316         return mMesh;
00317 }
00318 
00319 //-----------------------------------------------------------------------------
00320 // LLViewerJointMesh::setMesh()
00321 //-----------------------------------------------------------------------------
00322 void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
00323 {
00324         // set the mesh pointer
00325         mMesh = mesh;
00326 
00327         // release any existing skin joints
00328         freeSkinData();
00329 
00330         if ( mMesh == NULL )
00331         {
00332                 return;
00333         }
00334 
00335         // acquire the transform from the mesh object
00336         setPosition( mMesh->getPosition() );
00337         setRotation( mMesh->getRotation() );
00338         setScale( mMesh->getScale() );
00339 
00340         // create skin joints if necessary
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                         //llinfos << "Setting up joint " << jointNames[jn].c_str() << llendl;
00352                         LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
00353                         mSkinJoints[jn].setupSkinJoint( joint );
00354                 }
00355         }
00356 
00357         // setup joint array
00358         if (!mMesh->isLOD())
00359         {
00360                 setupJoint((LLViewerJoint*)getRoot());
00361         }
00362 
00363 //      llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
00364 }
00365 
00366 //-----------------------------------------------------------------------------
00367 // setupJoint()
00368 //-----------------------------------------------------------------------------
00369 void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
00370 {
00371 //      llinfos << "Mesh: " << getName() << llendl;
00372 
00373 //      S32 joint_count = 0;
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                 // we've found a skinjoint for this joint..
00385 
00386                 // is the last joint in the array our parent?
00387                 if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
00388                 {
00389                         // ...then just add ourselves
00390                         LLViewerJoint* jointp = js.mJoint;
00391                         mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
00392 //                      llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
00393 //                      joint_count++;
00394                 }
00395                 // otherwise add our parent and ourselves
00396                 else
00397                 {
00398                         mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
00399 //                      llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
00400 //                      joint_count++;
00401                         mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
00402 //                      llinfos << "joint " << joint_count << current_joint->getName() << llendl;
00403 //                      joint_count++;
00404                 }
00405         }
00406 
00407         // depth-first traversal
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 // register layoud
00419 // rotation X 0-n
00420 // rotation Y 0-n
00421 // rotation Z 0-n
00422 // pivot parent 0-n -- child = n+1
00423 
00424 static LLMatrix4        gJointMatUnaligned[32];
00425 static LLMatrix3        gJointRotUnaligned[32];
00426 static LLVector4        gJointPivot[32];
00427 
00428 //-----------------------------------------------------------------------------
00429 // uploadJointMatrices()
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         //calculate joint matrices
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         //upload joint pivots
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         //add pivot point into transform
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         // upload matrices
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                                 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector);
00503                                 U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
00504                                 memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
00505                                 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+6, (GLfloat*)vector);
00506                                 //cgGLSetParameterArray4f(gPipeline.mAvatarMatrix, offset, 1, vector);
00507                         }
00508                 }
00509                 glUniform4fvARB(gAvatarMatrixParam, 45, mat);
00510         }
00511 }
00512 
00513 //--------------------------------------------------------------------
00514 // LLViewerJointMesh::drawBone()
00515 //--------------------------------------------------------------------
00516 void LLViewerJointMesh::drawBone()
00517 {
00518 }
00519 
00520 //--------------------------------------------------------------------
00521 // LLViewerJointMesh::isTransparent()
00522 //--------------------------------------------------------------------
00523 BOOL LLViewerJointMesh::isTransparent()
00524 {
00525         return mIsTransparent;
00526 }
00527 
00528 //--------------------------------------------------------------------
00529 // DrawElementsBLEND and utility code
00530 //--------------------------------------------------------------------
00531 
00532 // compate_int is used by the qsort function to sort the index array
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 // LLViewerJointMesh::drawShape()
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         // setup current color
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         // setup current texture
00608         //----------------------------------------------------------------
00609         llassert( !(mTexture.notNull() && mLayerSet) );  // mutually exclusive
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);  // GL_TEXTURE_ENV_COLOR is set in renderPass1
00677                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00678                 }
00679         }
00680         else
00681         {
00682                 //----------------------------------------------------------------
00683                 // by default, backface culling is enabled
00684                 //----------------------------------------------------------------
00685                 /*if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER)
00686                 {
00687                         LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
00688 
00689                         glClientActiveTextureARB(GL_TEXTURE0_ARB);
00690                         glActiveTextureARB(GL_TEXTURE0_ARB);
00691                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00692                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_MODULATE);
00693                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_REPLACE);
00694 
00695                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_TEXTURE);
00696                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00697 
00698                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_PRIMARY_COLOR_ARB);
00699                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00700 
00701                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_PRIMARY_COLOR_ARB);
00702                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00703 
00704                         glClientActiveTextureARB(GL_TEXTURE1_ARB);
00705                         glEnable(GL_TEXTURE_2D); // Texture unit 1
00706                         glActiveTextureARB(GL_TEXTURE1_ARB);
00707                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00708                         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,        sClothingInnerColor.mV);
00709                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_INTERPOLATE_ARB);
00710                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_REPLACE);
00711 
00712                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_PREVIOUS_ARB);
00713                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00714 
00715                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_CONSTANT_ARB);
00716                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00717 
00718                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_PREVIOUS_ARB);
00719                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00720 
00721                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB,           GL_TEXTURE);
00722                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB,          GL_SRC_ALPHA);
00723                 }
00724                 else if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_OUTER)
00725                 {
00726                         glAlphaFunc(GL_GREATER, 0.1f);
00727                         LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D );
00728 
00729                         glClientActiveTextureARB(GL_TEXTURE0_ARB);
00730                         glActiveTextureARB(GL_TEXTURE0_ARB);
00731                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00732                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_MODULATE);
00733                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_REPLACE);
00734 
00735                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_TEXTURE);
00736                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00737 
00738                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_PRIMARY_COLOR_ARB);
00739                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00740 
00741                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_PRIMARY_COLOR_ARB);
00742                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00743 
00744                         glClientActiveTextureARB(GL_TEXTURE1_ARB);
00745                         glEnable(GL_TEXTURE_2D); // Texture unit 1
00746                         glActiveTextureARB(GL_TEXTURE1_ARB);
00747                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00748                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_REPLACE);
00749                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_MODULATE);
00750 
00751                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00752                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00753 
00754                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_TEXTURE);
00755                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
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         /*if (sRenderPass != AVATAR_RENDER_PASS_SINGLE)
00798         {
00799                 LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
00800                 glActiveTextureARB(GL_TEXTURE1_ARB);
00801                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_MODULATE);
00802 
00803                 // Return to the default texture.
00804                 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00805                 glClientActiveTextureARB(GL_TEXTURE0_ARB);
00806                 glActiveTextureARB(GL_TEXTURE0_ARB);
00807 
00808                 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_MODULATE);
00809                 glAlphaFunc(GL_GREATER, 0.01f);
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 // updateFaceSizes()
00826 //-----------------------------------------------------------------------------
00827 void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
00828 {
00829         // Do a pre-alloc pass to determine sizes of data.
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 // updateFaceData()
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         // Copy data into the faces from the polymesh data.
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 // updateLOD()
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 // static
00914 void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
00915 {
00916         LLStrider<LLVector3> o_vertices;
00917         LLStrider<LLVector3> o_normals;
00918 
00919         //get vertex and normal striders
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                 // blend by first matrix
00936                 F32 w = weights[index]; 
00937                 
00938                 // Maybe we don't have to change gBlendMat.
00939                 // Profiles of a single-avatar scene on a Mac show this to be a very
00940                 // common case.  JC
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                 // No lerp required in this case.
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                 // Try to keep all the accesses to the matrix data as close
00964                 // together as possible.  This function is a hot spot on the
00965                 // Mac. JC
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; // 8K samples before overflow
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                 // Once we've measured performance, just run the specified
01038                 // code version.
01039                 if(sUpdateGeometryFunc == updateGeometryOriginal)
01040                         uploadJointMatrices();
01041                 sUpdateGeometryFunc(mFace, mMesh);
01042         }
01043         else
01044         {
01045                 // At startup, measure the amount of time in skinning and choose
01046                 // the fastest one.
01047                 LLTimer ug_timer ;
01048                 
01049                 if (sUpdateGeometryCallPointer)
01050                 {
01051                         if(sUpdateGeometryFunc == updateGeometryOriginal)
01052                                 uploadJointMatrices();
01053                         // call accelerated version for this processor
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                                 // First set of run data is with vectorization off.
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                                 // Second set of run data is with vectorization on.
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                                         // In case user runs test again, force reset of data on
01130                                         // next run.
01131                                         sUpdateGeometryGlobalTime = 0.0;
01132 
01133                                         // We have data now on which version is faster.  Switch to that
01134                                         // code and save the data for next run.
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                                                 // SIMD decreases performance, fall back to original code
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                         // calculate joint to which this skinned vertex is bound
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                 // add offset to move rigid mesh to target location
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 // End

Generated on Thu Jul 1 06:09:28 2010 for Second Life Viewer by  doxygen 1.4.7