00001
00032
00033
00034
00035 #include "llviewerprecompiledheaders.h"
00036
00037 #include "llpolymorph.h"
00038 #include "llvoavatar.h"
00039 #include "llxmltree.h"
00040 #include "llendianswizzle.h"
00041
00042
00043
00044 const F32 NORMAL_SOFTEN_FACTOR = 0.65f;
00045
00046
00047
00048
00049 LLPolyMorphData::LLPolyMorphData(char *morph_name)
00050 {
00051 llassert (morph_name);
00052
00053 mName = new char[strlen(morph_name) + 1];
00054 strcpy(mName, morph_name);
00055
00056 mNumIndices = 0;
00057 mCurrentIndex = 0;
00058 mTotalDistortion = 0.f;
00059 mAvgDistortion.zeroVec();
00060 mMaxDistortion = 0.f;
00061 mVertexIndices = NULL;
00062 mCoords = NULL;
00063 mNormals = NULL;
00064 mBinormals = NULL;
00065 mTexCoords = NULL;
00066
00067 mMesh = NULL;
00068 }
00069
00070
00071
00072
00073 LLPolyMorphData::~LLPolyMorphData()
00074 {
00075 delete [] mName;
00076 delete [] mVertexIndices;
00077 delete [] mCoords;
00078 delete [] mNormals;
00079 delete [] mBinormals;
00080 delete [] mTexCoords;
00081 }
00082
00083
00084
00085
00086 BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh)
00087 {
00088 S32 numVertices;
00089 S32 numRead;
00090
00091 numRead = fread(&numVertices, sizeof(S32), 1, fp);
00092 llendianswizzle(&numVertices, sizeof(S32), 1);
00093 if (numRead != 1)
00094 {
00095 llwarns << "Can't read number of morph target vertices" << llendl;
00096 return FALSE;
00097 }
00098
00099
00100
00101
00102 mCoords = new LLVector3[numVertices];
00103 mNormals = new LLVector3[numVertices];
00104 mBinormals = new LLVector3[numVertices];
00105 mTexCoords = new LLVector2[numVertices];
00106
00107 mVertexIndices = new U32[numVertices];
00108 mNumIndices = 0;
00109 mTotalDistortion = 0.f;
00110 mMaxDistortion = 0.f;
00111 mAvgDistortion.zeroVec();
00112 mMesh = mesh;
00113
00114
00115
00116
00117 for(S32 v = 0; v < numVertices; v++)
00118 {
00119 numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp);
00120 llendianswizzle(&mVertexIndices[v], sizeof(U32), 1);
00121 if (numRead != 1)
00122 {
00123 llwarns << "Can't read morph target vertex number" << llendl;
00124 return FALSE;
00125 }
00126
00127 if (mVertexIndices[v] > 10000)
00128 {
00129 llerrs << "Bad morph index: " << mVertexIndices[v] << llendl;
00130 }
00131
00132
00133 numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp);
00134 llendianswizzle(&mCoords[v].mV, sizeof(F32), 3);
00135 if (numRead != 3)
00136 {
00137 llwarns << "Can't read morph target vertex coordinates" << llendl;
00138 return FALSE;
00139 }
00140
00141 F32 magnitude = mCoords[v].magVec();
00142
00143 mTotalDistortion += magnitude;
00144 mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]);
00145 mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]);
00146 mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]);
00147
00148 if (magnitude > mMaxDistortion)
00149 {
00150 mMaxDistortion = magnitude;
00151 }
00152
00153 numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp);
00154 llendianswizzle(&mNormals[v].mV, sizeof(F32), 3);
00155 if (numRead != 3)
00156 {
00157 llwarns << "Can't read morph target normal" << llendl;
00158 return FALSE;
00159 }
00160
00161 numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp);
00162 llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3);
00163 if (numRead != 3)
00164 {
00165 llwarns << "Can't read morph target binormal" << llendl;
00166 return FALSE;
00167 }
00168
00169
00170 numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp);
00171 llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2);
00172 if (numRead != 2)
00173 {
00174 llwarns << "Can't read morph target uv" << llendl;
00175 return FALSE;
00176 }
00177
00178 mNumIndices++;
00179 }
00180
00181 mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices);
00182 mAvgDistortion.normVec();
00183
00184 return TRUE;
00185 }
00186
00187
00188
00189
00190 LLPolyMorphTargetInfo::LLPolyMorphTargetInfo()
00191 : mIsClothingMorph(FALSE)
00192 {
00193 }
00194
00195 BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
00196 {
00197 llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) );
00198
00199 if (!LLViewerVisualParamInfo::parseXml(node))
00200 return FALSE;
00201
00202
00203 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
00204 if( !node->getFastAttributeString( name_string, mMorphName ) )
00205 {
00206 llwarns << "Avatar file: <param> is missing name attribute" << llendl;
00207 return FALSE;
00208 }
00209
00210 static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph");
00211 node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph);
00212
00213 LLXmlTreeNode *paramNode = node->getChildByName("param_morph");
00214
00215 if (NULL == paramNode)
00216 {
00217 llwarns << "Failed to getChildByName(\"param_morph\")"
00218 << llendl;
00219 return FALSE;
00220 }
00221
00222 for (LLXmlTreeNode* child_node = paramNode->getFirstChild();
00223 child_node;
00224 child_node = paramNode->getNextChild())
00225 {
00226 static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
00227 if (child_node->hasName("volume_morph"))
00228 {
00229 LLString volume_name;
00230 if (child_node->getFastAttributeString(name_string, volume_name))
00231 {
00232 LLVector3 scale;
00233 static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
00234 child_node->getFastAttributeVector3(scale_string, scale);
00235
00236 LLVector3 pos;
00237 static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
00238 child_node->getFastAttributeVector3(pos_string, pos);
00239
00240 mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos));
00241 }
00242 }
00243 }
00244
00245 return TRUE;
00246 }
00247
00248
00249
00250
00251 LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
00252 : mMorphData(NULL), mMesh(poly_mesh),
00253 mVertMask(NULL),
00254 mLastSex(SEX_FEMALE),
00255 mNumMorphMasksPending(0)
00256 {
00257 }
00258
00259
00260
00261
00262 LLPolyMorphTarget::~LLPolyMorphTarget()
00263 {
00264 if (mVertMask)
00265 {
00266 delete mVertMask;
00267 }
00268 }
00269
00270
00271
00272
00273 BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
00274 {
00275 llassert(mInfo == NULL);
00276 if (info->mID < 0)
00277 return FALSE;
00278 mInfo = info;
00279 mID = info->mID;
00280 setWeight(getDefaultWeight(), FALSE );
00281
00282 LLVOAvatar* avatarp = mMesh->getAvatar();
00283 LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
00284 for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++)
00285 {
00286 LLPolyVolumeMorphInfo *volume_info = &(*iter);
00287 std::string vol_string(volume_info->mName);
00288 for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++)
00289 {
00290 if (avatarp->mCollisionVolumes[i].getName() == vol_string)
00291 {
00292 mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
00293 volume_info->mScale,
00294 volume_info->mPos));
00295 break;
00296 }
00297 }
00298 }
00299
00300 mMorphData = mMesh->getMorphData(getInfo()->mMorphName.c_str());
00301 if (!mMorphData)
00302 {
00303 llwarns << "No morph target named " << getInfo()->mMorphName << " found in mesh." << llendl;
00304 return FALSE;
00305 }
00306 return TRUE;
00307 }
00308
00309 #if 0 // obsolete
00310
00311
00312
00313 BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node)
00314 {
00315 LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo;
00316
00317 info->parseXml(node);
00318 if (!setInfo(info))
00319 {
00320 delete info;
00321 return FALSE;
00322 }
00323 return TRUE;
00324 }
00325 #endif
00326
00327
00328
00329
00330 LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh)
00331 {
00332 if (!mMorphData || mMesh != mesh) return LLVector3::zero;
00333
00334 for(U32 index = 0; index < mMorphData->mNumIndices; index++)
00335 {
00336 if (mMorphData->mVertexIndices[index] == (U32)requested_index)
00337 {
00338 return mMorphData->mCoords[index];
00339 }
00340 }
00341
00342 return LLVector3::zero;
00343 }
00344
00345
00346
00347
00348 const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
00349 {
00350 if (!mMorphData) return &LLVector3::zero;
00351
00352 LLVector3* resultVec;
00353 mMorphData->mCurrentIndex = 0;
00354 if (mMorphData->mNumIndices)
00355 {
00356 resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
00357 if (index != NULL)
00358 {
00359 *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
00360 }
00361 if (poly_mesh != NULL)
00362 {
00363 *poly_mesh = mMesh;
00364 }
00365
00366 return resultVec;
00367 }
00368 return NULL;
00369 }
00370
00371
00372
00373
00374 const LLVector3 *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
00375 {
00376 if (!mMorphData) return &LLVector3::zero;
00377
00378 LLVector3* resultVec;
00379 mMorphData->mCurrentIndex++;
00380 if (mMorphData->mCurrentIndex < mMorphData->mNumIndices)
00381 {
00382 resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
00383 if (index != NULL)
00384 {
00385 *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
00386 }
00387 if (poly_mesh != NULL)
00388 {
00389 *poly_mesh = mMesh;
00390 }
00391 return resultVec;
00392 }
00393 return NULL;
00394 }
00395
00396
00397
00398
00399 F32 LLPolyMorphTarget::getTotalDistortion()
00400 {
00401 if (mMorphData)
00402 {
00403 return mMorphData->mTotalDistortion;
00404 }
00405 else
00406 {
00407 return 0.f;
00408 }
00409 }
00410
00411
00412
00413
00414 const LLVector3& LLPolyMorphTarget::getAvgDistortion()
00415 {
00416 if (mMorphData)
00417 {
00418 return mMorphData->mAvgDistortion;
00419 }
00420 else
00421 {
00422 return LLVector3::zero;
00423 }
00424 }
00425
00426
00427
00428
00429 F32 LLPolyMorphTarget::getMaxDistortion()
00430 {
00431 if (mMorphData)
00432 {
00433 return mMorphData->mMaxDistortion;
00434 }
00435 else
00436 {
00437 return 0.f;
00438 }
00439 }
00440
00441
00442
00443
00444 void LLPolyMorphTarget::apply( ESex avatar_sex )
00445 {
00446 if (!mMorphData || mNumMorphMasksPending > 0)
00447 {
00448 return;
00449 }
00450
00451 mLastSex = avatar_sex;
00452
00453
00454 F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
00455
00456 mLastWeight += delta_weight;
00457
00458 if (delta_weight != 0.f)
00459 {
00460 llassert(!mMesh->isLOD());
00461 LLVector3 *coords = mMesh->getWritableCoords();
00462
00463 LLVector3 *scaled_normals = mMesh->getScaledNormals();
00464 LLVector3 *normals = mMesh->getWritableNormals();
00465
00466 LLVector3 *scaled_binormals = mMesh->getScaledBinormals();
00467 LLVector3 *binormals = mMesh->getWritableBinormals();
00468
00469 LLVector4 *clothing_weights = mMesh->getWritableClothingWeights();
00470 LLVector2 *tex_coords = mMesh->getWritableTexCoords();
00471
00472 F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
00473
00474 for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++)
00475 {
00476 S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph];
00477
00478 F32 maskWeight = 1.f;
00479 if (maskWeightArray)
00480 {
00481 maskWeight = maskWeightArray[vert_index_morph];
00482 }
00483
00484 coords[vert_index_mesh] += mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight;
00485 if (getInfo()->mIsClothingMorph && clothing_weights)
00486 {
00487 LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight;
00488 LLVector4* clothing_weight = &clothing_weights[vert_index_mesh];
00489 clothing_weight->mV[VX] += clothing_offset.mV[VX];
00490 clothing_weight->mV[VY] += clothing_offset.mV[VY];
00491 clothing_weight->mV[VZ] += clothing_offset.mV[VZ];
00492 clothing_weight->mV[VW] = maskWeight;
00493 }
00494
00495
00496 scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
00497 LLVector3 normalized_normal = scaled_normals[vert_index_mesh];
00498 normalized_normal.normVec();
00499 normals[vert_index_mesh] = normalized_normal;
00500
00501
00502 scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
00503 LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal;
00504 LLVector3 normalized_binormal = normalized_normal % tangent;
00505 normalized_binormal.normVec();
00506 binormals[vert_index_mesh] = normalized_binormal;
00507
00508 tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight;
00509 }
00510
00511
00512 for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ )
00513 {
00514 LLPolyVolumeMorph* volume_morph = &(*iter);
00515 LLVector3 scale_delta = volume_morph->mScale * delta_weight;
00516 LLVector3 pos_delta = volume_morph->mPos * delta_weight;
00517
00518 volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
00519 volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
00520 }
00521 }
00522
00523 if (mNext)
00524 {
00525 mNext->apply(avatar_sex);
00526 }
00527 }
00528
00529
00530
00531
00532 void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
00533 {
00534 LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL;
00535
00536 if (!mVertMask)
00537 {
00538 mVertMask = new LLPolyVertexMask(mMorphData);
00539 mNumMorphMasksPending--;
00540 }
00541 else
00542 {
00543
00544 F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
00545
00546 if (maskWeights)
00547 {
00548 LLVector3 *coords = mMesh->getWritableCoords();
00549 LLVector3 *scaled_normals = mMesh->getScaledNormals();
00550 LLVector3 *scaled_binormals = mMesh->getScaledBinormals();
00551 LLVector2 *tex_coords = mMesh->getWritableTexCoords();
00552
00553 for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++)
00554 {
00555 F32 lastMaskWeight = mLastWeight * maskWeights[vert];
00556 S32 out_vert = mMorphData->mVertexIndices[vert];
00557
00558
00559 coords[out_vert] -= mMorphData->mCoords[vert] * lastMaskWeight;
00560 scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR;
00561 scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR;
00562 tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight;
00563
00564 if (clothing_weights)
00565 {
00566 LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight;
00567 LLVector4* clothing_weight = &clothing_weights[out_vert];
00568 clothing_weight->mV[VX] -= clothing_offset.mV[VX];
00569 clothing_weight->mV[VY] -= clothing_offset.mV[VY];
00570 clothing_weight->mV[VZ] -= clothing_offset.mV[VZ];
00571 }
00572 }
00573 }
00574 }
00575
00576
00577 mLastWeight = 0.f;
00578
00579 mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights);
00580
00581 apply(mLastSex);
00582 }
00583
00584
00585
00586
00587
00588 LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
00589 {
00590 mWeights = new F32[morph_data->mNumIndices];
00591 mMorphData = morph_data;
00592 mWeightsGenerated = FALSE;
00593 }
00594
00595
00596
00597
00598 LLPolyVertexMask::~LLPolyVertexMask()
00599 {
00600 delete[] mWeights;
00601 }
00602
00603
00604
00605
00606 void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights)
00607 {
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 for (U32 index = 0; index < mMorphData->mNumIndices; index++)
00622 {
00623 S32 vertIndex = mMorphData->mVertexIndices[index];
00624 const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex);
00625 LLVector2 uvCoords;
00626
00627 if (sharedVertIndex)
00628 {
00629 uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex);
00630 }
00631 else
00632 {
00633 uvCoords = mMorphData->mMesh->getUVs(vertIndex);
00634 }
00635 U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1);
00636 U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1);
00637
00638 mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f;
00639
00640 if (invert)
00641 {
00642 mWeights[index] = 1.f - mWeights[index];
00643 }
00644
00645
00646
00647
00648 if (clothing_weights)
00649 {
00650 clothing_weights[vertIndex].mV[VW] = mWeights[index];
00651 }
00652 }
00653 mWeightsGenerated = TRUE;
00654 }
00655
00656
00657
00658
00659 F32* LLPolyVertexMask::getMorphMaskWeights()
00660 {
00661 if (!mWeightsGenerated)
00662 {
00663 return NULL;
00664 }
00665
00666 return mWeights;
00667 }