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