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