00001
00032
00033
00034
00035 #include "llviewerprecompiledheaders.h"
00036
00037 #include "imageids.h"
00038 #include "llfasttimer.h"
00039
00040 #include "llagent.h"
00041 #include "llapr.h"
00042 #include "llbox.h"
00043 #include "lldrawable.h"
00044 #include "lldrawpoolavatar.h"
00045 #include "lldrawpoolbump.h"
00046 #include "lldynamictexture.h"
00047 #include "llface.h"
00048 #include "llgldbg.h"
00049 #include "llglheaders.h"
00050 #include "lltexlayer.h"
00051 #include "llviewercamera.h"
00052 #include "llviewercontrol.h"
00053 #include "llviewerimagelist.h"
00054 #include "llviewerjointmesh.h"
00055 #include "llvoavatar.h"
00056 #include "llsky.h"
00057 #include "pipeline.h"
00058 #include "llglslshader.h"
00059 #include "llmath.h"
00060 #include "v4math.h"
00061 #include "m3math.h"
00062 #include "m4math.h"
00063
00064 #if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS
00065 extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
00066 extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
00067 extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
00068 #endif
00069 extern BOOL gRenderForSelect;
00070
00071 static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
00072 static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
00073 LLVertexBuffer::MAP_NORMAL |
00074 LLVertexBuffer::MAP_TEXCOORD;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 LLSkinJoint::LLSkinJoint()
00087 {
00088 mJoint = NULL;
00089 }
00090
00091
00092
00093
00094 LLSkinJoint::~LLSkinJoint()
00095 {
00096 mJoint = NULL;
00097 }
00098
00099
00100
00101
00102
00103 BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
00104 {
00105
00106 mJoint = joint;
00107 if ( !mJoint )
00108 {
00109 llinfos << "Can't find joint" << llendl;
00110 }
00111
00112
00113 mRootToJointSkinOffset.clearVec();
00114
00115 LLVector3 rootSkinOffset;
00116 while (joint)
00117 {
00118 rootSkinOffset += joint->getSkinOffset();
00119 joint = (LLViewerJoint*)joint->getParent();
00120 }
00121
00122 mRootToJointSkinOffset = -rootSkinOffset;
00123 mRootToParentJointSkinOffset = mRootToJointSkinOffset;
00124 mRootToParentJointSkinOffset += mJoint->getSkinOffset();
00125
00126 return TRUE;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136 BOOL LLViewerJointMesh::sPipelineRender = FALSE;
00137 EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
00138 U32 LLViewerJointMesh::sClothingMaskImageName = 0;
00139 LLColor4 LLViewerJointMesh::sClothingInnerColor;
00140
00141
00142
00143
00144 LLViewerJointMesh::LLViewerJointMesh()
00145 :
00146 mTexture( NULL ),
00147 mLayerSet( NULL ),
00148 mTestImageName( 0 ),
00149 mIsTransparent(FALSE)
00150 {
00151
00152 mColor[0] = 1.0f;
00153 mColor[1] = 1.0f;
00154 mColor[2] = 1.0f;
00155 mColor[3] = 1.0f;
00156 mShiny = 0.0f;
00157 mCullBackFaces = TRUE;
00158
00159 mMesh = NULL;
00160
00161 mNumSkinJoints = 0;
00162 mSkinJoints = NULL;
00163
00164 mFace = NULL;
00165
00166 mMeshID = 0;
00167 mUpdateXform = FALSE;
00168
00169 mValid = FALSE;
00170 }
00171
00172
00173
00174
00175
00176
00177 LLViewerJointMesh::~LLViewerJointMesh()
00178 {
00179 mMesh = NULL;
00180 mTexture = NULL;
00181 freeSkinData();
00182 }
00183
00184
00185
00186
00187
00188 BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
00189 {
00190 mSkinJoints = new LLSkinJoint[ numSkinJoints ];
00191 mNumSkinJoints = numSkinJoints;
00192 return TRUE;
00193 }
00194
00195
00196
00197
00198 void LLViewerJointMesh::freeSkinData()
00199 {
00200 mNumSkinJoints = 0;
00201 delete [] mSkinJoints;
00202 mSkinJoints = NULL;
00203 }
00204
00205
00206
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
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
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 void LLViewerJointMesh::setTexture( LLViewerImage *texture )
00240 {
00241 mTexture = texture;
00242
00243
00244 if( texture )
00245 {
00246 mLayerSet = NULL;
00247
00248
00249 }
00250 }
00251
00252
00253
00254
00255
00256 void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
00257 {
00258 mLayerSet = layer_set;
00259
00260
00261 if( layer_set )
00262 {
00263 mTexture = NULL;
00264 }
00265 }
00266
00267
00268
00269
00270
00271
00272 LLPolyMesh *LLViewerJointMesh::getMesh()
00273 {
00274 return mMesh;
00275 }
00276
00277
00278
00279
00280 void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
00281 {
00282
00283 mMesh = mesh;
00284
00285
00286 freeSkinData();
00287
00288 if ( mMesh == NULL )
00289 {
00290 return;
00291 }
00292
00293
00294 setPosition( mMesh->getPosition() );
00295 setRotation( mMesh->getRotation() );
00296 setScale( mMesh->getScale() );
00297
00298
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
00310 LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
00311 mSkinJoints[jn].setupSkinJoint( joint );
00312 }
00313 }
00314
00315
00316 if (!mMesh->isLOD())
00317 {
00318 setupJoint((LLViewerJoint*)getRoot());
00319 }
00320
00321
00322 }
00323
00324
00325
00326
00327 void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
00328 {
00329
00330
00331
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
00343
00344
00345 if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == ¤t_joint->getParent()->getWorldMatrix())
00346 {
00347
00348 LLViewerJoint* jointp = js.mJoint;
00349 mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
00350
00351
00352 }
00353
00354 else
00355 {
00356 mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getParent()->getWorldMatrix(), NULL));
00357
00358
00359 mMesh->mJointRenderData.put(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js));
00360
00361
00362 }
00363 }
00364
00365
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
00377
00378
00379
00380
00381
00382 static LLMatrix4 gJointMatUnaligned[32];
00383 static LLMatrix3 gJointRotUnaligned[32];
00384 static LLVector4 gJointPivot[32];
00385
00386
00387
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
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
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
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
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
00461 U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
00462 memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
00463
00464
00465 }
00466 }
00467 glUniform4fvARB(gAvatarMatrixParam, 45, mat);
00468 }
00469 }
00470
00471
00472
00473
00474 void LLViewerJointMesh::drawBone()
00475 {
00476 }
00477
00478
00479
00480
00481 BOOL LLViewerJointMesh::isTransparent()
00482 {
00483 return mIsTransparent;
00484 }
00485
00486
00487
00488
00489
00490
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
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
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
00534
00535 llassert( !(mTexture.notNull() && mLayerSet) );
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);
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
00659
00660 void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
00661 {
00662
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
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
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
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
00746 void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
00747 {
00748 LLStrider<LLVector3> o_vertices;
00749 LLStrider<LLVector3> o_normals;
00750
00751
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
00768 F32 w = weights[index];
00769
00770
00771
00772
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
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
00796
00797
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;
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
00856 void (*LLViewerJointMesh::sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh);
00857
00858
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;
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
00912
00913 if(sUpdateGeometryFunc == updateGeometryOriginal)
00914 uploadJointMatrices();
00915 sUpdateGeometryFunc(mFace, mMesh);
00916 }
00917 else
00918 {
00919
00920
00921 LLTimer ug_timer ;
00922
00923 if (sUpdateGeometryCallPointer)
00924 {
00925 if(sUpdateGeometryFunc == updateGeometryOriginal)
00926 uploadJointMatrices();
00927
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
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
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
01004
01005 sUpdateGeometryGlobalTime = 0.0;
01006
01007
01008
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
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