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 // LLViewerJointMesh::freeSkinData()
00197 //-----------------------------------------------------------------------------
00198 void LLViewerJointMesh::freeSkinData()
00199 {
00200         mNumSkinJoints = 0;
00201         delete [] mSkinJoints;
00202         mSkinJoints = NULL;
00203 }
00204 
00205 //--------------------------------------------------------------------
00206 // LLViewerJointMesh::getColor()
00207 //--------------------------------------------------------------------
00208 void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
00209 {
00210         *red   = mColor[0];
00211         *green = mColor[1];
00212         *blue  = mColor[2];
00213         *alpha = mColor[3];
00214 }
00215 
00216 //--------------------------------------------------------------------
00217 // LLViewerJointMesh::setColor()
00218 //--------------------------------------------------------------------
00219 void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
00220 {
00221         mColor[0] = red;
00222         mColor[1] = green;
00223         mColor[2] = blue;
00224         mColor[3] = alpha;
00225 }
00226 
00227 
00228 //--------------------------------------------------------------------
00229 // LLViewerJointMesh::getTexture()
00230 //--------------------------------------------------------------------
00231 //LLViewerImage *LLViewerJointMesh::getTexture()
00232 //{
00233 //      return mTexture;
00234 //}
00235 
00236 //--------------------------------------------------------------------
00237 // LLViewerJointMesh::setTexture()
00238 //--------------------------------------------------------------------
00239 void LLViewerJointMesh::setTexture( LLViewerImage *texture )
00240 {
00241         mTexture = texture;
00242 
00243         // texture and dynamic_texture are mutually exclusive
00244         if( texture )
00245         {
00246                 mLayerSet = NULL;
00247                 //texture->bindTexture(0);
00248                 //texture->setClamp(TRUE, TRUE);
00249         }
00250 }
00251 
00252 //--------------------------------------------------------------------
00253 // LLViewerJointMesh::setLayerSet()
00254 // Sets the shape texture (takes precedence over normal texture)
00255 //--------------------------------------------------------------------
00256 void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
00257 {
00258         mLayerSet = layer_set;
00259         
00260         // texture and dynamic_texture are mutually exclusive
00261         if( layer_set )
00262         {
00263                 mTexture = NULL;
00264         }
00265 }
00266 
00267 
00268 
00269 //--------------------------------------------------------------------
00270 // LLViewerJointMesh::getMesh()
00271 //--------------------------------------------------------------------
00272 LLPolyMesh *LLViewerJointMesh::getMesh()
00273 {
00274         return mMesh;
00275 }
00276 
00277 //-----------------------------------------------------------------------------
00278 // LLViewerJointMesh::setMesh()
00279 //-----------------------------------------------------------------------------
00280 void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
00281 {
00282         // set the mesh pointer
00283         mMesh = mesh;
00284 
00285         // release any existing skin joints
00286         freeSkinData();
00287 
00288         if ( mMesh == NULL )
00289         {
00290                 return;
00291         }
00292 
00293         // acquire the transform from the mesh object
00294         setPosition( mMesh->getPosition() );
00295         setRotation( mMesh->getRotation() );
00296         setScale( mMesh->getScale() );
00297 
00298         // create skin joints if necessary
00299         if ( mMesh->hasWeights() && !mMesh->isLOD())
00300         {
00301                 U32 numJointNames = mMesh->getNumJointNames();
00302                 
00303                 allocateSkinData( numJointNames );
00304                 std::string *jointNames = mMesh->getJointNames();
00305 
00306                 U32 jn;
00307                 for (jn = 0; jn < numJointNames; jn++)
00308                 {
00309                         //llinfos << "Setting up joint " << jointNames[jn].c_str() << llendl;
00310                         LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
00311                         mSkinJoints[jn].setupSkinJoint( joint );
00312                 }
00313         }
00314 
00315         // setup joint array
00316         if (!mMesh->isLOD())
00317         {
00318                 setupJoint((LLViewerJoint*)getRoot());
00319         }
00320 
00321 //      llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
00322 }
00323 
00324 //-----------------------------------------------------------------------------
00325 // setupJoint()
00326 //-----------------------------------------------------------------------------
00327 void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
00328 {
00329 //      llinfos << "Mesh: " << getName() << llendl;
00330 
00331 //      S32 joint_count = 0;
00332         U32 sj;
00333         for (sj=0; sj<mNumSkinJoints; sj++)
00334         {
00335                 LLSkinJoint &js = mSkinJoints[sj];
00336 
00337                 if (js.mJoint != current_joint)
00338                 {
00339                         continue;
00340                 }
00341 
00342                 // we've found a skinjoint for this joint..
00343 
00344                 // is the last joint in the array our parent?
00345                 if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
00346                 {
00347                         // ...then just add ourselves
00348                         LLViewerJoint* jointp = js.mJoint;
00349                         mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
00350 //                      llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
00351 //                      joint_count++;
00352                 }
00353                 // otherwise add our parent and ourselves
00354                 else
00355                 {
00356                         mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
00357 //                      llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
00358 //                      joint_count++;
00359                         mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
00360 //                      llinfos << "joint " << joint_count << current_joint->getName() << llendl;
00361 //                      joint_count++;
00362                 }
00363         }
00364 
00365         // depth-first traversal
00366         for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
00367                  iter != current_joint->mChildren.end(); ++iter)
00368         {
00369                 LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
00370                 setupJoint(child_joint);
00371         }
00372 }
00373 
00374 const S32 NUM_AXES = 3;
00375 
00376 // register layoud
00377 // rotation X 0-n
00378 // rotation Y 0-n
00379 // rotation Z 0-n
00380 // pivot parent 0-n -- child = n+1
00381 
00382 static LLMatrix4        gJointMatUnaligned[32];
00383 static LLMatrix3        gJointRotUnaligned[32];
00384 static LLVector4        gJointPivot[32];
00385 
00386 //-----------------------------------------------------------------------------
00387 // uploadJointMatrices()
00388 //-----------------------------------------------------------------------------
00389 void LLViewerJointMesh::uploadJointMatrices()
00390 {
00391         S32 joint_num;
00392         LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
00393         LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
00394         BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
00395 
00396         //calculate joint matrices
00397         for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00398         {
00399                 LLMatrix4 joint_mat = *reference_mesh->mJointRenderData[joint_num]->mWorldMatrix;
00400 
00401                 if (hardware_skinning)
00402                 {
00403                         joint_mat *= LLDrawPoolAvatar::getModelView();
00404                 }
00405                 gJointMatUnaligned[joint_num] = joint_mat;
00406                 gJointRotUnaligned[joint_num] = joint_mat.getMat3();
00407         }
00408 
00409         BOOL last_pivot_uploaded = FALSE;
00410         S32 j = 0;
00411 
00412         //upload joint pivots
00413         for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00414         {
00415                 LLSkinJoint *sj = reference_mesh->mJointRenderData[joint_num]->mSkinJoint;
00416                 if (sj)
00417                 {
00418                         if (!last_pivot_uploaded)
00419                         {
00420                                 LLVector4 parent_pivot(sj->mRootToParentJointSkinOffset);
00421                                 parent_pivot.mV[VW] = 0.f;
00422                                 gJointPivot[j++] = parent_pivot;
00423                         }
00424 
00425                         LLVector4 child_pivot(sj->mRootToJointSkinOffset);
00426                         child_pivot.mV[VW] = 0.f;
00427 
00428                         gJointPivot[j++] = child_pivot;
00429 
00430                         last_pivot_uploaded = TRUE;
00431                 }
00432                 else
00433                 {
00434                         last_pivot_uploaded = FALSE;
00435                 }
00436         }
00437 
00438         //add pivot point into transform
00439         for (S32 i = 0; i < j; i++)
00440         {
00441                 LLVector3 pivot;
00442                 pivot = LLVector3(gJointPivot[i]);
00443                 pivot = pivot * gJointRotUnaligned[i];
00444                 gJointMatUnaligned[i].translate(pivot);
00445         }
00446 
00447         // upload matrices
00448         if (hardware_skinning)
00449         {
00450                 GLfloat mat[45*4];
00451                 memset(mat, 0, sizeof(GLfloat)*45*4);
00452 
00453                 for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
00454                 {
00455                         gJointMatUnaligned[joint_num].transpose();
00456 
00457                         for (S32 axis = 0; axis < NUM_AXES; axis++)
00458                         {
00459                                 F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis];
00460                                 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+5, (GLfloat*)vector);
00461                                 U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
00462                                 memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
00463                                 //glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, LL_CHARACTER_MAX_JOINTS_PER_MESH * axis + joint_num+6, (GLfloat*)vector);
00464                                 //cgGLSetParameterArray4f(gPipeline.mAvatarMatrix, offset, 1, vector);
00465                         }
00466                 }
00467                 glUniform4fvARB(gAvatarMatrixParam, 45, mat);
00468         }
00469 }
00470 
00471 //--------------------------------------------------------------------
00472 // LLViewerJointMesh::drawBone()
00473 //--------------------------------------------------------------------
00474 void LLViewerJointMesh::drawBone()
00475 {
00476 }
00477 
00478 //--------------------------------------------------------------------
00479 // LLViewerJointMesh::isTransparent()
00480 //--------------------------------------------------------------------
00481 BOOL LLViewerJointMesh::isTransparent()
00482 {
00483         return mIsTransparent;
00484 }
00485 
00486 //--------------------------------------------------------------------
00487 // DrawElementsBLEND and utility code
00488 //--------------------------------------------------------------------
00489 
00490 // compate_int is used by the qsort function to sort the index array
00491 int compare_int(const void *a, const void *b)
00492 {
00493         if (*(U32*)a < *(U32*)b)
00494         {
00495                 return -1;
00496         }
00497         else if (*(U32*)a > *(U32*)b)
00498         {
00499                 return 1;
00500         }
00501         else return 0;
00502 }
00503 
00504 //--------------------------------------------------------------------
00505 // LLViewerJointMesh::drawShape()
00506 //--------------------------------------------------------------------
00507 U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass)
00508 {
00509         if (!mValid || !mMesh || !mFace || !mVisible || 
00510                 mFace->mVertexBuffer.isNull() ||
00511                 mMesh->getNumFaces() == 0) 
00512         {
00513                 return 0;
00514         }
00515 
00516         U32 triangle_count = 0;
00517 
00518         stop_glerror();
00519         
00520         //----------------------------------------------------------------
00521         // setup current color
00522         //----------------------------------------------------------------
00523         if (!gRenderForSelect)
00524         {
00525                 glColor4fv(mColor.mV);
00526         }
00527 
00528         stop_glerror();
00529         
00530         LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
00531 
00532         //----------------------------------------------------------------
00533         // setup current texture
00534         //----------------------------------------------------------------
00535         llassert( !(mTexture.notNull() && mLayerSet) );  // mutually exclusive
00536 
00537         if (mTestImageName)
00538         {
00539                 LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D ); 
00540 
00541                 if (mIsTransparent)
00542                 {
00543                         glColor4f(1.f, 1.f, 1.f, 1.f);
00544                 }
00545                 else
00546                 {
00547                         glColor4f(0.7f, 0.6f, 0.3f, 1.f);
00548                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00549                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_INTERPOLATE_ARB);
00550 
00551                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00552                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00553 
00554                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_TEXTURE);
00555                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00556                         
00557                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB,           GL_TEXTURE);
00558                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB,          GL_ONE_MINUS_SRC_ALPHA);
00559                 }
00560         }
00561         else if( mLayerSet )
00562         {
00563                 if(     mLayerSet->hasComposite() )
00564                 {
00565                         mLayerSet->getComposite()->bindTexture();
00566                 }
00567                 else
00568                 {
00569                         llwarns << "Layerset without composite" << llendl;
00570                         gImageList.getImage(IMG_DEFAULT)->bind();
00571                 }
00572         }
00573         else
00574         if ( mTexture.notNull() )
00575         {
00576                 mTexture->bind();
00577                 if (!mTexture->getClampS()) {
00578                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00579                 }
00580                 if (!mTexture->getClampT()) {
00581                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00582                 }
00583         }
00584         else
00585         {
00586                 gImageList.getImage(IMG_DEFAULT_AVATAR)->bind();
00587         }
00588         
00589         if (gRenderForSelect)
00590         {
00591                 if (isTransparent())
00592                 {
00593                         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00594                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_REPLACE);
00595                         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_MODULATE);
00596 
00597                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00598                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00599 
00600                         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_TEXTURE);  // GL_TEXTURE_ENV_COLOR is set in renderPass1
00601                         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00602                 }
00603                 else
00604                 {
00605                         LLImageGL::unbindTexture(0);
00606                 }
00607         }
00608         
00609         mFace->mVertexBuffer->setBuffer(sRenderMask);
00610 
00611         U32 start = mMesh->mFaceVertexOffset;
00612         U32 end = start + mMesh->mFaceVertexCount - 1;
00613         U32 count = mMesh->mFaceIndexCount;
00614         U32 offset = mMesh->mFaceIndexOffset;
00615 
00616         if (mMesh->hasWeights())
00617         {
00618                 if ((mFace->getPool()->getVertexShaderLevel() > 0))
00619                 {
00620                         if (first_pass)
00621                         {
00622                                 uploadJointMatrices();
00623                         }
00624                 }
00625                 
00626                 mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
00627         }
00628         else
00629         {
00630                 glPushMatrix();
00631                 LLMatrix4 jointToWorld = getWorldMatrix();
00632                 glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
00633                 mFace->mVertexBuffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
00634                 glPopMatrix();
00635         }
00636         gPipeline.addTrianglesDrawn(count/3);
00637 
00638         triangle_count += count;
00639         
00640         if (mTestImageName)
00641         {
00642                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00643         }
00644 
00645         if (mTexture.notNull()) {
00646                 if (!mTexture->getClampS()) {
00647                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
00648                 }
00649                 if (!mTexture->getClampT()) {
00650                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
00651                 }
00652         }
00653 
00654         return triangle_count;
00655 }
00656 
00657 //-----------------------------------------------------------------------------
00658 // updateFaceSizes()
00659 //-----------------------------------------------------------------------------
00660 void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
00661 {
00662         // Do a pre-alloc pass to determine sizes of data.
00663         if (mMesh && mValid)
00664         {
00665                 mMesh->mFaceVertexOffset = num_vertices;
00666                 mMesh->mFaceVertexCount = mMesh->getNumVertices();
00667                 mMesh->mFaceIndexOffset = num_indices;
00668                 mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
00669 
00670                 mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount;
00671 
00672                 num_vertices += mMesh->getNumVertices();
00673                 num_indices += mMesh->mFaceIndexCount;
00674         }
00675 }
00676 
00677 //-----------------------------------------------------------------------------
00678 // updateFaceData()
00679 //-----------------------------------------------------------------------------
00680 void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
00681 {
00682         mFace = face;
00683 
00684         if (mFace->mVertexBuffer.isNull())
00685         {
00686                 return;
00687         }
00688 
00689         LLStrider<LLVector3> verticesp;
00690         LLStrider<LLVector3> normalsp;
00691         LLStrider<LLVector2> tex_coordsp;
00692         LLStrider<F32>           vertex_weightsp;
00693         LLStrider<LLVector4> clothing_weightsp;
00694         LLStrider<U16> indicesp;
00695 
00696         // Copy data into the faces from the polymesh data.
00697         if (mMesh && mValid)
00698         {
00699                 if (mMesh->getNumVertices())
00700                 {
00701                         stop_glerror();
00702                         face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
00703                         stop_glerror();
00704                         face->mVertexBuffer->getIndexStrider(indicesp);
00705                         stop_glerror();
00706 
00707                         for (U16 i = 0; i < mMesh->getNumVertices(); i++)
00708                         {
00709                                 verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i);
00710                                 tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i);
00711                                 normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i);
00712                                 vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i);
00713                                 if (damp_wind)
00714                                 {
00715                                         clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0);
00716                                 }
00717                                 else
00718                                 {
00719                                         clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i));
00720                                 }
00721                         }
00722 
00723                         for (S32 i = 0; i < mMesh->getNumFaces(); i++)
00724                         {
00725                                 for (U32 j = 0; j < 3; j++)
00726                                 {
00727                                         U32 k = i*3+j+mMesh->mFaceIndexOffset;
00728                                         indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset;
00729                                 }
00730                         }
00731                 }
00732         }
00733 }
00734 
00735 //-----------------------------------------------------------------------------
00736 // updateLOD()
00737 //-----------------------------------------------------------------------------
00738 BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate)
00739 {
00740         BOOL valid = mValid;
00741         setValid(activate, TRUE);
00742         return (valid != activate);
00743 }
00744 
00745 // static
00746 void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
00747 {
00748         LLStrider<LLVector3> o_vertices;
00749         LLStrider<LLVector3> o_normals;
00750 
00751         //get vertex and normal striders
00752         LLVertexBuffer *buffer = mFace->mVertexBuffer;
00753         buffer->getVertexStrider(o_vertices,  0);
00754         buffer->getNormalStrider(o_normals,   0);
00755 
00756         F32 last_weight = F32_MAX;
00757         LLMatrix4 gBlendMat;
00758         LLMatrix3 gBlendRotMat;
00759 
00760         const F32* weights = mMesh->getWeights();
00761         const LLVector3* coords = mMesh->getCoords();
00762         const LLVector3* normals = mMesh->getNormals();
00763         for (U32 index = 0; index < mMesh->getNumVertices(); index++)
00764         {
00765                 U32 bidx = index + mMesh->mFaceVertexOffset;
00766                 
00767                 // blend by first matrix
00768                 F32 w = weights[index]; 
00769                 
00770                 // Maybe we don't have to change gBlendMat.
00771                 // Profiles of a single-avatar scene on a Mac show this to be a very
00772                 // common case.  JC
00773                 if (w == last_weight)
00774                 {
00775                         o_vertices[bidx] = coords[index] * gBlendMat;
00776                         o_normals[bidx] = normals[index] * gBlendRotMat;
00777                         continue;
00778                 }
00779                 
00780                 last_weight = w;
00781 
00782                 S32 joint = llfloor(w);
00783                 w -= joint;
00784                 
00785                 // No lerp required in this case.
00786                 if (w == 1.0f)
00787                 {
00788                         gBlendMat = gJointMatUnaligned[joint+1];
00789                         o_vertices[bidx] = coords[index] * gBlendMat;
00790                         gBlendRotMat = gJointRotUnaligned[joint+1];
00791                         o_normals[bidx] = normals[index] * gBlendRotMat;
00792                         continue;
00793                 }
00794                 
00795                 // Try to keep all the accesses to the matrix data as close
00796                 // together as possible.  This function is a hot spot on the
00797                 // Mac. JC
00798                 LLMatrix4 &m0 = gJointMatUnaligned[joint+1];
00799                 LLMatrix4 &m1 = gJointMatUnaligned[joint+0];
00800                 
00801                 gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
00802                 gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
00803                 gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
00804 
00805                 gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
00806                 gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
00807                 gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
00808 
00809                 gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
00810                 gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
00811                 gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
00812 
00813                 gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
00814                 gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
00815                 gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
00816 
00817                 o_vertices[bidx] = coords[index] * gBlendMat;
00818                 
00819                 LLMatrix3 &n0 = gJointRotUnaligned[joint+1];
00820                 LLMatrix3 &n1 = gJointRotUnaligned[joint+0];
00821                 
00822                 gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
00823                 gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
00824                 gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
00825 
00826                 gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
00827                 gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
00828                 gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
00829 
00830                 gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
00831                 gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
00832                 gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
00833                 
00834                 o_normals[bidx] = normals[index] * gBlendRotMat;
00835         }
00836 
00837         buffer->setBuffer(0);
00838 }
00839 
00840 const U32 UPDATE_GEOMETRY_CALL_MASK                     = 0x1FFF; // 8K samples before overflow
00841 const U32 UPDATE_GEOMETRY_CALL_OVERFLOW         = ~UPDATE_GEOMETRY_CALL_MASK;
00842 static bool sUpdateGeometryCallPointer          = false;
00843 static F64 sUpdateGeometryGlobalTime            = 0.0 ;
00844 static F64 sUpdateGeometryElapsedTime           = 0.0 ;
00845 static F64 sUpdateGeometryElapsedTimeOff        = 0.0 ;
00846 static F64 sUpdateGeometryElapsedTimeOn         = 0.0 ;
00847 static F64 sUpdateGeometryRunAvgOff[10];
00848 static F64 sUpdateGeometryRunAvgOn[10];
00849 static U32 sUpdateGeometryRunCount                      = 0 ;
00850 static U32 sUpdateGeometryCalls                         = 0 ;
00851 static U32 sUpdateGeometryLastProcessor         = 0 ;
00852 static BOOL sVectorizePerfTest                          = FALSE;
00853 static U32 sVectorizeProcessor                          = 0;
00854 
00855 //static
00856 void (*LLViewerJointMesh::sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh);
00857 
00858 //static
00859 void LLViewerJointMesh::updateVectorize()
00860 {
00861         sVectorizePerfTest = gSavedSettings.getBOOL("VectorizePerfTest");
00862         sVectorizeProcessor = gSavedSettings.getU32("VectorizeProcessor");
00863         BOOL vectorizeEnable = gSavedSettings.getBOOL("VectorizeEnable");
00864         BOOL vectorizeSkin = gSavedSettings.getBOOL("VectorizeSkin");
00865 
00866         std::string vp;
00867         switch(sVectorizeProcessor)
00868         {
00869                 case 2: vp = "SSE2"; break;                                     // *TODO: replace the magic #s
00870                 case 1: vp = "SSE"; break;
00871                 default: vp = "COMPILER DEFAULT"; break;
00872         }
00873         LL_INFOS("AppInit") << "Vectorization         : " << ( vectorizeEnable ? "ENABLED" : "DISABLED" ) << LL_ENDL ;
00874         LL_INFOS("AppInit") << "Vector Processor      : " << vp << LL_ENDL ;
00875         LL_INFOS("AppInit") << "Vectorized Skinning   : " << ( vectorizeSkin ? "ENABLED" : "DISABLED" ) << LL_ENDL ;
00876         if(vectorizeEnable && vectorizeSkin)
00877         {
00878                 switch(sVectorizeProcessor)
00879                 {
00880                         case 2:
00881                                 sUpdateGeometryFunc = &updateGeometrySSE2;
00882                                 break;
00883                         case 1:
00884                                 sUpdateGeometryFunc = &updateGeometrySSE;
00885                                 break;
00886                         default:
00887                                 sUpdateGeometryFunc = &updateGeometryVectorized;
00888                                 break;
00889                 }
00890         }
00891         else
00892         {
00893                 sUpdateGeometryFunc = &updateGeometryOriginal;
00894         }
00895 }
00896 
00897 void LLViewerJointMesh::updateGeometry()
00898 {
00899         if (!(mValid
00900                   && mMesh
00901                   && mFace
00902                   && mMesh->hasWeights()
00903                   && mFace->mVertexBuffer.notNull()
00904                   && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0))
00905         {
00906                 return;
00907         }
00908 
00909         if (!sVectorizePerfTest)
00910         {
00911                 // Once we've measured performance, just run the specified
00912                 // code version.
00913                 if(sUpdateGeometryFunc == updateGeometryOriginal)
00914                         uploadJointMatrices();
00915                 sUpdateGeometryFunc(mFace, mMesh);
00916         }
00917         else
00918         {
00919                 // At startup, measure the amount of time in skinning and choose
00920                 // the fastest one.
00921                 LLTimer ug_timer ;
00922                 
00923                 if (sUpdateGeometryCallPointer)
00924                 {
00925                         if(sUpdateGeometryFunc == updateGeometryOriginal)
00926                                 uploadJointMatrices();
00927                         // call accelerated version for this processor
00928                         sUpdateGeometryFunc(mFace, mMesh);
00929                 }
00930                 else
00931                 {
00932                         uploadJointMatrices();
00933                         updateGeometryOriginal(mFace, mMesh);
00934                 }
00935         
00936                 sUpdateGeometryElapsedTime += ug_timer.getElapsedTimeF64();
00937                 ++sUpdateGeometryCalls;
00938                 if(0 != (sUpdateGeometryCalls & UPDATE_GEOMETRY_CALL_OVERFLOW))
00939                 {
00940                         F64 time_since_app_start = ug_timer.getElapsedSeconds();
00941                         if(sUpdateGeometryGlobalTime == 0.0 
00942                                 || sUpdateGeometryLastProcessor != sVectorizeProcessor)
00943                         {
00944                                 sUpdateGeometryGlobalTime               = time_since_app_start;
00945                                 sUpdateGeometryElapsedTime              = 0;
00946                                 sUpdateGeometryCalls                    = 0;
00947                                 sUpdateGeometryRunCount                 = 0;
00948                                 sUpdateGeometryLastProcessor    = sVectorizeProcessor;
00949                                 sUpdateGeometryCallPointer              = false;
00950                                 return;
00951                         }
00952                         F64 percent_time_in_function = 
00953                                 ( sUpdateGeometryElapsedTime * 100.0 ) / ( time_since_app_start - sUpdateGeometryGlobalTime ) ;
00954                         sUpdateGeometryGlobalTime = time_since_app_start;
00955                         if (!sUpdateGeometryCallPointer)
00956                         {
00957                                 // First set of run data is with vectorization off.
00958                                 sUpdateGeometryCallPointer = true;
00959                                 llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
00960                                         << "vectorize off " << percent_time_in_function
00961                                         << "% of time with "
00962                                         << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
00963                                         << " seconds per call "
00964                                         << llendl;
00965                                 sUpdateGeometryRunAvgOff[sUpdateGeometryRunCount] = percent_time_in_function;
00966                                 sUpdateGeometryElapsedTimeOff += sUpdateGeometryElapsedTime;
00967                                 sUpdateGeometryCalls = 0;
00968                         }
00969                         else
00970                         {
00971                                 // Second set of run data is with vectorization on.
00972                                 sUpdateGeometryCallPointer = false;
00973                                 llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
00974                                         << "VEC on " << percent_time_in_function
00975                                         << "% of time with "
00976                                         << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
00977                                         << " seconds per call "
00978                                         << llendl;
00979                                 sUpdateGeometryRunAvgOn[sUpdateGeometryRunCount] = percent_time_in_function ;
00980                                 sUpdateGeometryElapsedTimeOn += sUpdateGeometryElapsedTime;
00981 
00982                                 sUpdateGeometryCalls = 0;
00983                                 sUpdateGeometryRunCount++;
00984                                 F64 a = 0.0, b = 0.0;
00985                                 for(U32 i = 0; i<sUpdateGeometryRunCount; i++)
00986                                 {
00987                                         a += sUpdateGeometryRunAvgOff[i];
00988                                         b += sUpdateGeometryRunAvgOn[i];
00989                                 }
00990                                 a /= sUpdateGeometryRunCount;
00991                                 b /= sUpdateGeometryRunCount;
00992                                 F64 perf_boost = ( sUpdateGeometryElapsedTimeOff - sUpdateGeometryElapsedTimeOn ) / sUpdateGeometryElapsedTimeOn;
00993                                 llinfos << "run averages (" << (F64)sUpdateGeometryRunCount
00994                                         << "/10) vectorize off " << a
00995                                         << "% : vectorize type " << sVectorizeProcessor
00996                                         << " " << b
00997                                         << "% : performance boost " 
00998                                         << perf_boost * 100.0
00999                                         << "%"
01000                                         << llendl ;
01001                                 if(sUpdateGeometryRunCount == 10)
01002                                 {
01003                                         // In case user runs test again, force reset of data on
01004                                         // next run.
01005                                         sUpdateGeometryGlobalTime = 0.0;
01006 
01007                                         // We have data now on which version is faster.  Switch to that
01008                                         // code and save the data for next run.
01009                                         gSavedSettings.setBOOL("VectorizePerfTest", FALSE);
01010 
01011                                         if (perf_boost > 0.0)
01012                                         {
01013                                                 llinfos << "Vectorization improves avatar skinning performance, "
01014                                                         << "keeping on for future runs."
01015                                                         << llendl;
01016                                                 gSavedSettings.setBOOL("VectorizeSkin", TRUE);
01017                                         }
01018                                         else
01019                                         {
01020                                                 // SIMD decreases performance, fall back to original code
01021                                                 llinfos << "Vectorization decreases avatar skinning performance, "
01022                                                         << "switching back to original code."
01023                                                         << llendl;
01024 
01025                                                 gSavedSettings.setBOOL("VectorizeSkin", FALSE);
01026                                         }
01027                                 }
01028                         }
01029                         sUpdateGeometryElapsedTime = 0.0f;
01030                 }
01031         }
01032 }
01033 
01034 void LLViewerJointMesh::dump()
01035 {
01036         if (mValid)
01037         {
01038                 llinfos << "Usable LOD " << mName << llendl;
01039         }
01040 }
01041 
01042 // End

Generated on Fri May 16 08:34:10 2008 for SecondLife by  doxygen 1.5.5