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