00001
00032
00033
00034
00035 #include "llviewerprecompiledheaders.h"
00036
00037 #include "llpolymesh.h"
00038
00039 #include "llviewercontrol.h"
00040 #include "llxmltree.h"
00041 #include "llvoavatar.h"
00042 #include "lldir.h"
00043 #include "llvolume.h"
00044 #include "llendianswizzle.h"
00045
00046 #include "llfasttimer.h"
00047
00048 #define HEADER_ASCII "Linden Mesh 1.0"
00049 #define HEADER_BINARY "Linden Binary Mesh 1.0"
00050
00051 extern LLControlGroup gSavedSettings;
00052
00053
00054
00055
00056 LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList;
00057
00058
00059
00060
00061 LLPolyMeshSharedData::LLPolyMeshSharedData()
00062 {
00063 mNumVertices = 0;
00064 mBaseCoords = NULL;
00065 mBaseNormals = NULL;
00066 mBaseBinormals = NULL;
00067 mTexCoords = NULL;
00068 mDetailTexCoords = NULL;
00069 mWeights = NULL;
00070 mHasWeights = FALSE;
00071 mHasDetailTexCoords = FALSE;
00072
00073 mNumFaces = 0;
00074 mFaces = NULL;
00075
00076 mNumJointNames = 0;
00077 mJointNames = NULL;
00078
00079 mTriangleIndices = NULL;
00080 mNumTriangleIndices = 0;
00081
00082 mReferenceData = NULL;
00083
00084 mLastIndexOffset = -1;
00085 }
00086
00087
00088
00089
00090 LLPolyMeshSharedData::~LLPolyMeshSharedData()
00091 {
00092 freeMeshData();
00093 mMorphData.deleteAllData();
00094 }
00095
00096
00097
00098
00099 void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data)
00100 {
00101 mReferenceData = reference_data;
00102
00103 if (reference_data)
00104 {
00105 mBaseCoords = reference_data->mBaseCoords;
00106 mBaseNormals = reference_data->mBaseNormals;
00107 mBaseBinormals = reference_data->mBaseBinormals;
00108 mTexCoords = reference_data->mTexCoords;
00109 mDetailTexCoords = reference_data->mDetailTexCoords;
00110 mWeights = reference_data->mWeights;
00111 mHasWeights = reference_data->mHasWeights;
00112 mHasDetailTexCoords = reference_data->mHasDetailTexCoords;
00113 }
00114 }
00115
00116
00117
00118
00119 void LLPolyMeshSharedData::freeMeshData()
00120 {
00121 if (!mReferenceData)
00122 {
00123 mNumVertices = 0;
00124
00125 delete [] mBaseCoords;
00126 mBaseCoords = NULL;
00127
00128 delete [] mBaseNormals;
00129 mBaseNormals = NULL;
00130
00131 delete [] mBaseBinormals;
00132 mBaseBinormals = NULL;
00133
00134 delete [] mTexCoords;
00135 mTexCoords = NULL;
00136
00137 delete [] mDetailTexCoords;
00138 mDetailTexCoords = NULL;
00139
00140 delete [] mWeights;
00141 mWeights = NULL;
00142 }
00143
00144 mNumFaces = 0;
00145 delete [] mFaces;
00146 mFaces = NULL;
00147
00148 mNumJointNames = 0;
00149 delete [] mJointNames;
00150 mJointNames = NULL;
00151
00152 delete [] mTriangleIndices;
00153 mTriangleIndices = NULL;
00154
00155
00156 }
00157
00158
00159 int compare_int(const void *a, const void *b);
00160
00161
00162
00163
00164 void LLPolyMeshSharedData::genIndices(S32 index_offset)
00165 {
00166 if (index_offset == mLastIndexOffset)
00167 {
00168 return;
00169 }
00170
00171 delete []mTriangleIndices;
00172 mTriangleIndices = new U32[mNumTriangleIndices];
00173
00174 S32 cur_index = 0;
00175 for (S32 i = 0; i < mNumFaces; i++)
00176 {
00177 mTriangleIndices[cur_index] = mFaces[i][0] + index_offset;
00178 cur_index++;
00179 mTriangleIndices[cur_index] = mFaces[i][1] + index_offset;
00180 cur_index++;
00181 mTriangleIndices[cur_index] = mFaces[i][2] + index_offset;
00182 cur_index++;
00183 }
00184
00185 mLastIndexOffset = index_offset;
00186 }
00187
00188
00189
00190
00191 U32 LLPolyMeshSharedData::getNumKB()
00192 {
00193 U32 num_kb = sizeof(LLPolyMesh);
00194
00195 if (!isLOD())
00196 {
00197 num_kb += mNumVertices *
00198 ( sizeof(LLVector3) +
00199 sizeof(LLVector3) +
00200 sizeof(LLVector2) );
00201 }
00202
00203 if (mHasDetailTexCoords && !isLOD())
00204 {
00205 num_kb += mNumVertices * sizeof(LLVector2);
00206 }
00207
00208 if (mHasWeights && !isLOD())
00209 {
00210 num_kb += mNumVertices * sizeof(float);
00211 }
00212
00213 num_kb += mNumFaces * sizeof(LLPolyFace);
00214
00215 num_kb /= 1024;
00216 return num_kb;
00217 }
00218
00219
00220
00221
00222 BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices )
00223 {
00224 U32 i;
00225 mBaseCoords = new LLVector3[ numVertices ];
00226 mBaseNormals = new LLVector3[ numVertices ];
00227 mBaseBinormals = new LLVector3[ numVertices ];
00228 mTexCoords = new LLVector2[ numVertices ];
00229 mDetailTexCoords = new LLVector2[ numVertices ];
00230 mWeights = new F32[ numVertices ];
00231 for (i = 0; i < numVertices; i++)
00232 {
00233 mWeights[i] = 0.f;
00234 }
00235 mNumVertices = numVertices;
00236 return TRUE;
00237 }
00238
00239
00240
00241
00242 BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces )
00243 {
00244 mFaces = new LLPolyFace[ numFaces ];
00245 mNumFaces = numFaces;
00246 mNumTriangleIndices = mNumFaces * 3;
00247 return TRUE;
00248 }
00249
00250
00251
00252
00253 BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames )
00254 {
00255 mJointNames = new std::string[ numJointNames ];
00256 mNumJointNames = numJointNames;
00257 return TRUE;
00258 }
00259
00260
00261
00262
00263 BOOL LLPolyMeshSharedData::loadMesh( const char *fileName )
00264 {
00265
00266
00267
00268 if(!fileName)
00269 {
00270 llerrs << "Filename is Empty!" << llendl;
00271 return FALSE;
00272 }
00273 FILE* fp = LLFile::fopen(fileName, "rb");
00274 if (!fp)
00275 {
00276 llerrs << "can't open: " << fileName << llendl;
00277 return FALSE;
00278 }
00279
00280
00281
00282
00283 char header[128];
00284 if (fread(header, sizeof(char), 128, fp) != 128)
00285 {
00286 llwarns << "Short read" << llendl;
00287 }
00288
00289
00290
00291
00292 BOOL status = FALSE;
00293 if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 )
00294 {
00295 lldebugs << "Loading " << fileName << llendl;
00296
00297
00298
00299
00300 fseek(fp, 24, SEEK_SET);
00301
00302
00303
00304
00305 U8 hasWeights;
00306 size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp);
00307 if (numRead != 1)
00308 {
00309 llerrs << "can't read HasWeights flag from " << fileName << llendl;
00310 return FALSE;
00311 }
00312 if (!isLOD())
00313 {
00314 mHasWeights = (hasWeights==0) ? FALSE : TRUE;
00315 }
00316
00317
00318
00319
00320 U8 hasDetailTexCoords;
00321 numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp);
00322 if (numRead != 1)
00323 {
00324 llerrs << "can't read HasDetailTexCoords flag from " << fileName << llendl;
00325 return FALSE;
00326 }
00327
00328
00329
00330
00331 LLVector3 position;
00332 numRead = fread(position.mV, sizeof(float), 3, fp);
00333 llendianswizzle(position.mV, sizeof(float), 3);
00334 if (numRead != 3)
00335 {
00336 llerrs << "can't read Position from " << fileName << llendl;
00337 return FALSE;
00338 }
00339 setPosition( position );
00340
00341
00342
00343
00344 LLVector3 rotationAngles;
00345 numRead = fread(rotationAngles.mV, sizeof(float), 3, fp);
00346 llendianswizzle(rotationAngles.mV, sizeof(float), 3);
00347 if (numRead != 3)
00348 {
00349 llerrs << "can't read RotationAngles from " << fileName << llendl;
00350 return FALSE;
00351 }
00352
00353 U8 rotationOrder;
00354 numRead = fread(&rotationOrder, sizeof(U8), 1, fp);
00355
00356 if (numRead != 1)
00357 {
00358 llerrs << "can't read RotationOrder from " << fileName << llendl;
00359 return FALSE;
00360 }
00361
00362 rotationOrder = 0;
00363
00364 setRotation( mayaQ( rotationAngles.mV[0],
00365 rotationAngles.mV[1],
00366 rotationAngles.mV[2],
00367 (LLQuaternion::Order)rotationOrder ) );
00368
00369
00370
00371
00372 LLVector3 scale;
00373 numRead = fread(scale.mV, sizeof(float), 3, fp);
00374 llendianswizzle(scale.mV, sizeof(float), 3);
00375 if (numRead != 3)
00376 {
00377 llerrs << "can't read Scale from " << fileName << llendl;
00378 return FALSE;
00379 }
00380 setScale( scale );
00381
00382
00383
00384
00385 freeMeshData();
00386
00387 U16 numVertices = 0;
00388
00389
00390
00391
00392 if (!isLOD())
00393 {
00394 numRead = fread(&numVertices, sizeof(U16), 1, fp);
00395 llendianswizzle(&numVertices, sizeof(U16), 1);
00396 if (numRead != 1)
00397 {
00398 llerrs << "can't read NumVertices from " << fileName << llendl;
00399 return FALSE;
00400 }
00401
00402 allocateVertexData( numVertices );
00403
00404
00405
00406
00407 numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp);
00408 llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices);
00409 if (numRead != numVertices)
00410 {
00411 llerrs << "can't read Coordinates from " << fileName << llendl;
00412 return FALSE;
00413 }
00414
00415
00416
00417
00418 numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp);
00419 llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices);
00420 if (numRead != numVertices)
00421 {
00422 llerrs << " can't read Normals from " << fileName << llendl;
00423 return FALSE;
00424 }
00425
00426
00427
00428
00429 numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp);
00430 llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices);
00431 if (numRead != numVertices)
00432 {
00433 llerrs << " can't read Binormals from " << fileName << llendl;
00434 return FALSE;
00435 }
00436
00437
00438
00439
00440
00441 numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp);
00442 llendianswizzle(mTexCoords, sizeof(float), 2*numVertices);
00443 if (numRead != numVertices)
00444 {
00445 llerrs << "can't read TexCoords from " << fileName << llendl;
00446 return FALSE;
00447 }
00448
00449
00450
00451
00452 if (mHasDetailTexCoords)
00453 {
00454 numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp);
00455 llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices);
00456 if (numRead != numVertices)
00457 {
00458 llerrs << "can't read DetailTexCoords from " << fileName << llendl;
00459 return FALSE;
00460 }
00461 }
00462
00463
00464
00465
00466 if (mHasWeights)
00467 {
00468 numRead = fread(mWeights, sizeof(float), numVertices, fp);
00469 llendianswizzle(mWeights, sizeof(float), numVertices);
00470 if (numRead != numVertices)
00471 {
00472 llerrs << "can't read Weights from " << fileName << llendl;
00473 return FALSE;
00474 }
00475 }
00476 }
00477
00478
00479
00480
00481 U16 numFaces;
00482 numRead = fread(&numFaces, sizeof(U16), 1, fp);
00483 llendianswizzle(&numFaces, sizeof(U16), 1);
00484 if (numRead != 1)
00485 {
00486 llerrs << "can't read NumFaces from " << fileName << llendl;
00487 return FALSE;
00488 }
00489 allocateFaceData( numFaces );
00490
00491
00492
00493
00494
00495 U32 i;
00496 U32 numTris = 0;
00497 for (i = 0; i < numFaces; i++)
00498 {
00499 S16 face[3];
00500 numRead = fread(face, sizeof(U16), 3, fp);
00501 llendianswizzle(face, sizeof(U16), 3);
00502 if (numRead != 3)
00503 {
00504 llerrs << "can't read Face[" << i << "] from " << fileName << llendl;
00505 return FALSE;
00506 }
00507 if (mReferenceData)
00508 {
00509 llassert(face[0] < mReferenceData->mNumVertices);
00510 llassert(face[1] < mReferenceData->mNumVertices);
00511 llassert(face[2] < mReferenceData->mNumVertices);
00512 }
00513
00514 if (isLOD())
00515 {
00516
00517 for (S32 j = 0; j < 3; j++)
00518 {
00519 if (face[j] > mNumVertices - 1)
00520 {
00521 mNumVertices = face[j] + 1;
00522 }
00523 }
00524 }
00525 mFaces[i][0] = face[0];
00526 mFaces[i][1] = face[1];
00527 mFaces[i][2] = face[2];
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 numTris++;
00542 }
00543
00544 lldebugs << "verts: " << numVertices
00545 << ", faces: " << numFaces
00546 << ", tris: " << numTris
00547 << llendl;
00548
00549
00550
00551
00552 if (!isLOD())
00553 {
00554 U16 numSkinJoints = 0;
00555 if ( mHasWeights )
00556 {
00557 numRead = fread(&numSkinJoints, sizeof(U16), 1, fp);
00558 llendianswizzle(&numSkinJoints, sizeof(U16), 1);
00559 if (numRead != 1)
00560 {
00561 llerrs << "can't read NumSkinJoints from " << fileName << llendl;
00562 return FALSE;
00563 }
00564 allocateJointNames( numSkinJoints );
00565 }
00566
00567
00568
00569
00570 for (i=0; i < numSkinJoints; i++)
00571 {
00572 char jointName[64+1];
00573 numRead = fread(jointName, sizeof(jointName)-1, 1, fp);
00574 jointName[sizeof(jointName)-1] = '\0';
00575 if (numRead != 1)
00576 {
00577 llerrs << "can't read Skin[" << i << "].Name from " << fileName << llendl;
00578 return FALSE;
00579 }
00580
00581 std::string *jn = &mJointNames[i];
00582 *jn = jointName;
00583 }
00584
00585
00586
00587
00588 char morphName[64+1];
00589 morphName[sizeof(morphName)-1] = '\0';
00590 while(fread(&morphName, sizeof(char), 64, fp) == 64)
00591 {
00592 if (!strcmp(morphName, "End Morphs"))
00593 {
00594
00595 break;
00596 }
00597 LLPolyMorphData* morph_data = new LLPolyMorphData(morphName);
00598
00599 BOOL result = morph_data->loadBinary(fp, this);
00600
00601 if (!result)
00602 {
00603 delete morph_data;
00604 continue;
00605 }
00606
00607 mMorphData.addData(morph_data);
00608 }
00609
00610 S32 numRemaps;
00611 if (fread(&numRemaps, sizeof(S32), 1, fp) == 1)
00612 {
00613 llendianswizzle(&numRemaps, sizeof(S32), 1);
00614 for (S32 i = 0; i < numRemaps; i++)
00615 {
00616 S32 remapSrc;
00617 S32 remapDst;
00618 if (fread(&remapSrc, sizeof(S32), 1, fp) != 1)
00619 {
00620 llerrs << "can't read source vertex in vertex remap data" << llendl;
00621 break;
00622 }
00623 if (fread(&remapDst, sizeof(S32), 1, fp) != 1)
00624 {
00625 llerrs << "can't read destination vertex in vertex remap data" << llendl;
00626 break;
00627 }
00628 llendianswizzle(&remapSrc, sizeof(S32), 1);
00629 llendianswizzle(&remapDst, sizeof(S32), 1);
00630
00631 mSharedVerts[remapSrc] = remapDst;
00632 }
00633 }
00634 }
00635
00636 status = TRUE;
00637 }
00638 else
00639 {
00640 llerrs << "invalid mesh file header: " << fileName << llendl;
00641 status = FALSE;
00642 }
00643
00644 if (0 == mNumJointNames)
00645 {
00646 allocateJointNames(1);
00647 }
00648
00649 fclose( fp );
00650
00651 return status;
00652 }
00653
00654
00655
00656
00657 const S32 *LLPolyMeshSharedData::getSharedVert(S32 vert)
00658 {
00659 if (mSharedVerts.count(vert) > 0)
00660 {
00661 return &mSharedVerts[vert];
00662 }
00663 return NULL;
00664 }
00665
00666
00667
00668
00669 const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index)
00670 {
00671
00672 llassert((S32)index < mNumVertices);
00673
00674 return mTexCoords[index];
00675 }
00676
00677
00678
00679
00680 LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh)
00681 {
00682 llassert(shared_data);
00683
00684 mSharedData = shared_data;
00685 mReferenceMesh = reference_mesh;
00686 mAvatarp = NULL;
00687 mVertexData = NULL;
00688
00689 if (shared_data->isLOD() && reference_mesh)
00690 {
00691 mCoords = reference_mesh->mCoords;
00692 mNormals = reference_mesh->mNormals;
00693 mScaledNormals = reference_mesh->mScaledNormals;
00694 mBinormals = reference_mesh->mBinormals;
00695 mScaledBinormals = reference_mesh->mScaledBinormals;
00696 mTexCoords = reference_mesh->mTexCoords;
00697 mClothingWeights = reference_mesh->mClothingWeights;
00698 }
00699 else
00700 {
00701 #if 1 // Allocate memory without initializing every vector
00702
00703 int nverts = mSharedData->mNumVertices;
00704 int nfloats = nverts * (3*5 + 2 + 4);
00705 mVertexData = new F32[nfloats];
00706 int offset = 0;
00707 mCoords = (LLVector3*)(mVertexData + offset); offset += 3*nverts;
00708 mNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts;
00709 mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts;
00710 mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts;
00711 mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts;
00712 mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts;
00713 mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts;
00714 #else
00715 mCoords = new LLVector3[mSharedData->mNumVertices];
00716 mNormals = new LLVector3[mSharedData->mNumVertices];
00717 mScaledNormals = new LLVector3[mSharedData->mNumVertices];
00718 mBinormals = new LLVector3[mSharedData->mNumVertices];
00719 mScaledBinormals = new LLVector3[mSharedData->mNumVertices];
00720 mTexCoords = new LLVector2[mSharedData->mNumVertices];
00721 mClothingWeights = new LLVector4[mSharedData->mNumVertices];
00722 memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices);
00723 #endif
00724 initializeForMorph();
00725 }
00726 }
00727
00728
00729
00730
00731
00732 LLPolyMesh::~LLPolyMesh()
00733 {
00734 S32 i;
00735 for (i = 0; i < mJointRenderData.count(); i++)
00736 {
00737 delete mJointRenderData[i];
00738 mJointRenderData[i] = NULL;
00739 }
00740 #if 0 // These are now allocated as one big uninitialized chunk
00741 delete [] mCoords;
00742 delete [] mNormals;
00743 delete [] mScaledNormals;
00744 delete [] mBinormals;
00745 delete [] mScaledBinormals;
00746 delete [] mClothingWeights;
00747 delete [] mTexCoords;
00748 #else
00749 delete [] mVertexData;
00750 #endif
00751 }
00752
00753
00754
00755
00756
00757 LLPolyMesh *LLPolyMesh::getMesh(const LLString &name, LLPolyMesh* reference_mesh)
00758 {
00759
00760
00761
00762 LLPolyMeshSharedData **meshSharedData = sGlobalSharedMeshList.getValue(name);
00763 if (meshSharedData)
00764 {
00765
00766 LLPolyMesh *poly_mesh = new LLPolyMesh(*meshSharedData, reference_mesh);
00767 return poly_mesh;
00768 }
00769
00770
00771
00772
00773 char full_path[LL_MAX_PATH];
00774 snprintf(full_path, LL_MAX_PATH, "%s", (gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name.c_str())).c_str());
00775
00776 LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData();
00777 if (reference_mesh)
00778 {
00779 mesh_data->setupLOD(reference_mesh->getSharedData());
00780 }
00781 if ( ! mesh_data->loadMesh( full_path ) )
00782 {
00783 delete mesh_data;
00784 return NULL;
00785 }
00786
00787 LLPolyMesh *poly_mesh = new LLPolyMesh(mesh_data, reference_mesh);
00788
00789
00790 sGlobalSharedMeshList.addToTail(name, poly_mesh->mSharedData);
00791
00792 return poly_mesh;
00793 }
00794
00795
00796
00797
00798 void LLPolyMesh::freeAllMeshes()
00799 {
00800 U32 i;
00801
00802
00803 for (i=0; i<sGlobalSharedMeshList.length(); i++)
00804 {
00805
00806
00807 LLPolyMeshSharedData **shared_mesh_pp = sGlobalSharedMeshList.getValueAt(i);
00808
00809
00810 delete *shared_mesh_pp;
00811 }
00812
00813
00814 sGlobalSharedMeshList.removeAll();
00815 }
00816
00817 LLPolyMeshSharedData *LLPolyMesh::getSharedData() const
00818 {
00819 return mSharedData;
00820 }
00821
00822
00823
00824
00825
00826 void LLPolyMesh::dumpDiagInfo()
00827 {
00828
00829 U32 total_verts = 0;
00830 U32 total_faces = 0;
00831 U32 total_kb = 0;
00832
00833 char buf[1024];
00834
00835 llinfos << "-----------------------------------------------------" << llendl;
00836 llinfos << " Global PolyMesh Table (DEBUG only)" << llendl;
00837 llinfos << " Verts Faces Mem(KB) Name" << llendl;
00838 llinfos << "-----------------------------------------------------" << llendl;
00839
00840
00841 for (U32 i=0; i<sGlobalSharedMeshList.length(); i++)
00842 {
00843 std::string *mesh_name_p = sGlobalSharedMeshList.getIndexAt(i);
00844
00845 LLPolyMeshSharedData **mesh_pp = sGlobalSharedMeshList.getValueAt(i);
00846 LLPolyMeshSharedData &mesh = **mesh_pp;
00847
00848 S32 num_verts = mesh.mNumVertices;
00849 S32 num_faces = mesh.mNumFaces;
00850 U32 num_kb = mesh.getNumKB();
00851
00852 snprintf(buf, sizeof(buf), "%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name_p->c_str());
00853 llinfos << buf << llendl;
00854
00855 total_verts += num_verts;
00856 total_faces += num_faces;
00857 total_kb += num_kb;
00858 }
00859
00860 llinfos << "-----------------------------------------------------" << llendl;
00861 snprintf(buf, sizeof(buf), "%8d %8d %8d TOTAL", total_verts, total_faces, total_kb );
00862 llinfos << buf << llendl;
00863 llinfos << "-----------------------------------------------------" << llendl;
00864 }
00865
00866
00867
00868
00869 const LLVector3 *LLPolyMesh::getCoords() const
00870 {
00871 return mCoords;
00872 }
00873
00874
00875
00876
00877 LLVector3 *LLPolyMesh::getWritableCoords()
00878 {
00879 return mCoords;
00880 }
00881
00882
00883
00884
00885 LLVector3 *LLPolyMesh::getWritableNormals()
00886 {
00887 return mNormals;
00888 }
00889
00890
00891
00892
00893 LLVector3 *LLPolyMesh::getWritableBinormals()
00894 {
00895 return mBinormals;
00896 }
00897
00898
00899
00900
00901
00902 LLVector4 *LLPolyMesh::getWritableClothingWeights()
00903 {
00904 return mClothingWeights;
00905 }
00906
00907
00908
00909
00910 LLVector2 *LLPolyMesh::getWritableTexCoords()
00911 {
00912 return mTexCoords;
00913 }
00914
00915
00916
00917
00918 LLVector3 *LLPolyMesh::getScaledNormals()
00919 {
00920 return mScaledNormals;
00921 }
00922
00923
00924
00925
00926 LLVector3 *LLPolyMesh::getScaledBinormals()
00927 {
00928 return mScaledBinormals;
00929 }
00930
00931
00932
00933
00934
00935 void LLPolyMesh::initializeForMorph()
00936 {
00937 if (!mSharedData)
00938 return;
00939
00940 memcpy(mCoords, mSharedData->mBaseCoords, sizeof(LLVector3) * mSharedData->mNumVertices);
00941 memcpy(mNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices);
00942 memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices);
00943 memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices);
00944 memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices);
00945 memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices);
00946 memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices);
00947 }
00948
00949
00950
00951
00952 LLPolyMorphData* LLPolyMesh::getMorphData(const char *morph_name)
00953 {
00954 if (!mSharedData) return NULL;
00955 for (LLPolyMorphData *morph_data = mSharedData->mMorphData.getFirstData();
00956 morph_data;
00957 morph_data = mSharedData->mMorphData.getNextData())
00958 {
00959 if (!strcmp(morph_data->getName(), morph_name))
00960 {
00961 return morph_data;
00962 }
00963 }
00964 return NULL;
00965 }
00966
00967
00968
00969
00970 void LLPolyMesh::removeMorphData(LLPolyMorphData *morph_target)
00971 {
00972 if (!mSharedData) return;
00973
00974 mSharedData->mMorphData.removeData(morph_target);
00975 }
00976
00977
00978
00979
00980 void LLPolyMesh::deleteAllMorphData()
00981 {
00982 if (!mSharedData) return;
00983
00984 mSharedData->mMorphData.deleteAllData();
00985 }
00986
00987
00988
00989
00990 const F32* LLPolyMesh::getWeights() const
00991 {
00992 return mSharedData->mWeights;
00993 }
00994
00995
00996
00997
00998 F32* LLPolyMesh::getWritableWeights() const
00999 {
01000 return mSharedData->mWeights;
01001 }
01002
01003
01004
01005
01006 LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo()
01007 {
01008 }
01009
01010 BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node)
01011 {
01012 llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) );
01013
01014 if (!LLViewerVisualParamInfo::parseXml(node))
01015 return FALSE;
01016
01017 LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton");
01018
01019 if (NULL == skeletalParam)
01020 {
01021 llwarns << "Failed to getChildByName(\"param_skeleton\")"
01022 << llendl;
01023 return FALSE;
01024 }
01025
01026 for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() )
01027 {
01028 if (bone->hasName("bone"))
01029 {
01030 LLString name;
01031 LLVector3 scale;
01032 LLVector3 pos;
01033 BOOL haspos = FALSE;
01034
01035 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
01036 if (!bone->getFastAttributeString(name_string, name))
01037 {
01038 llwarns << "No bone name specified for skeletal param." << llendl;
01039 continue;
01040 }
01041
01042 static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
01043 if (!bone->getFastAttributeVector3(scale_string, scale))
01044 {
01045 llwarns << "No scale specified for bone " << name << "." << llendl;
01046 continue;
01047 }
01048
01049
01050 static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset");
01051 if (bone->getFastAttributeVector3(offset_string, pos))
01052 {
01053 haspos = TRUE;
01054 }
01055 mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos));
01056 }
01057 else
01058 {
01059 llwarns << "Unrecognized element " << bone->getName() << " in skeletal distortion" << llendl;
01060 continue;
01061 }
01062 }
01063 return TRUE;
01064 }
01065
01066
01067
01068
01069 LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp)
01070 {
01071 mAvatar = avatarp;
01072 mDefaultVec.setVec(0.001f, 0.001f, 0.001f);
01073 }
01074
01075
01076
01077
01078 LLPolySkeletalDistortion::~LLPolySkeletalDistortion()
01079 {
01080 }
01081
01082 BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
01083 {
01084 llassert(mInfo == NULL);
01085 if (info->mID < 0)
01086 return FALSE;
01087 mInfo = info;
01088 mID = info->mID;
01089 setWeight(getDefaultWeight(), FALSE );
01090
01091 LLPolySkeletalDistortionInfo::bone_info_list_t::iterator iter;
01092 for (iter = getInfo()->mBoneInfoList.begin(); iter != getInfo()->mBoneInfoList.end(); iter++)
01093 {
01094 LLPolySkeletalBoneInfo *bone_info = &(*iter);
01095 LLJoint* joint = mAvatar->getJoint(bone_info->mBoneName);
01096 if (!joint)
01097 {
01098 llwarns << "Joint " << bone_info->mBoneName << " not found." << llendl;
01099 continue;
01100 }
01101
01102 if (mJointScales.find(joint) != mJointScales.end())
01103 {
01104 llwarns << "Scale deformation already supplied for joint " << joint->getName() << "." << llendl;
01105 }
01106
01107
01108 mJointScales[joint] = bone_info->mScaleDeformation;
01109
01110
01111 for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
01112 iter != joint->mChildren.end(); ++iter)
01113 {
01114 LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
01115 if (child_joint->inheritScale())
01116 {
01117 LLVector3 childDeformation = LLVector3(child_joint->getScale());
01118 childDeformation.scaleVec(bone_info->mScaleDeformation);
01119 mJointScales[child_joint] = childDeformation;
01120 }
01121 }
01122
01123 if (bone_info->mHasPositionDeformation)
01124 {
01125 if (mJointOffsets.find(joint) != mJointOffsets.end())
01126 {
01127 llwarns << "Offset deformation already supplied for joint " << joint->getName() << "." << llendl;
01128 }
01129 mJointOffsets[joint] = bone_info->mPositionDeformation;
01130 }
01131 }
01132 return TRUE;
01133 }
01134
01135
01136
01137
01138 void LLPolySkeletalDistortion::apply( ESex avatar_sex )
01139 {
01140 F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight();
01141
01142 LLJoint* joint;
01143 joint_vec_map_t::iterator iter;
01144
01145 for (iter = mJointScales.begin();
01146 iter != mJointScales.end();
01147 iter++)
01148 {
01149 joint = iter->first;
01150 LLVector3 newScale = joint->getScale();
01151 LLVector3 scaleDelta = iter->second;
01152 newScale = newScale + (effective_weight * scaleDelta) - (mLastWeight * scaleDelta);
01153 joint->setScale(newScale);
01154 }
01155
01156 for (iter = mJointOffsets.begin();
01157 iter != mJointOffsets.end();
01158 iter++)
01159 {
01160 joint = iter->first;
01161 LLVector3 newPosition = joint->getPosition();
01162 LLVector3 positionDelta = iter->second;
01163 newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta);
01164 joint->setPosition(newPosition);
01165 }
01166
01167 if (mLastWeight != mCurWeight && !mIsAnimating)
01168 {
01169 mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1);
01170 }
01171 mLastWeight = mCurWeight;
01172 }
01173
01174