llpolymorph.cpp

Go to the documentation of this file.
00001 
00032 //-----------------------------------------------------------------------------
00033 // Header Files
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 //#include "../tools/imdebug/imdebug.h"
00044 
00045 const F32 NORMAL_SOFTEN_FACTOR = 0.65f;
00046 
00047 LLLinkedList<LLPolyMorphData> gLoadedMorphs;
00048 
00049 //-----------------------------------------------------------------------------
00050 // LLPolyMorphData()
00051 //-----------------------------------------------------------------------------
00052 LLPolyMorphData::LLPolyMorphData(char *morph_name)
00053 {
00054         llassert (morph_name);
00055 
00056         mName = new char[strlen(morph_name) + 1];       /*Flawfinder: ignore*/
00057         strcpy(mName, morph_name);      /*Flawfinder: ignore*/
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 // ~LLPolyMorphData()
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 // loadBinary()
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         // allocate vertices
00104         //-------------------------------------------------------------------------
00105         mCoords = new LLVector3[numVertices];
00106         mNormals = new LLVector3[numVertices];
00107         mBinormals = new LLVector3[numVertices];
00108         mTexCoords = new LLVector2[numVertices];
00109         // Actually, we are allocating more space than we need for the skiplist
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         // read vertices
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 // LLPolyMorphTargetInfo()
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         // Get mixed-case name
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;  // Continue, ignoring this tag
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 // LLPolyMorphTarget()
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 // ~LLPolyMorphTarget()
00266 //-----------------------------------------------------------------------------
00267 LLPolyMorphTarget::~LLPolyMorphTarget()
00268 {
00269         if (mVertMask)
00270         {
00271                 delete mVertMask;
00272         }
00273 }
00274 
00275 //-----------------------------------------------------------------------------
00276 // setInfo()
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;  // Continue, ignoring this tag
00310         }
00311         return TRUE;
00312 }
00313 
00314 #if 0 // obsolete
00315 //-----------------------------------------------------------------------------
00316 // parseData()
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 // getVertexDistortion()
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 // getFirstDistortion()
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 // getNextDistortion()
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 // getTotalDistortion()
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 // getAvgDistortion()
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 // getMaxDistortion()
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 // apply()
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         // perform differential update of morph
00459         F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
00460         // store last weight
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                         // calculate new normals based on half angles
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                         // calculate new binormals
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                 // now apply volume changes
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 // applyMask()
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                 // remove effect of previous mask
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                                 // remove effect of existing masked morph
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         // set last weight to 0, since we've removed the effect of this morph
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 // LLPolyVertexMask()
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 // ~LLPolyVertexMask()
00602 //-----------------------------------------------------------------------------
00603 LLPolyVertexMask::~LLPolyVertexMask()
00604 {
00605         delete[] mWeights;
00606 }
00607 
00608 //-----------------------------------------------------------------------------
00609 // generateMask()
00610 //-----------------------------------------------------------------------------
00611 void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights)
00612 {
00613 // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
00614 //      BOOL debugImg = FALSE; 
00615 //      if (debugImg)
00616 //      {
00617 //              if (invert)
00618 //              {
00619 //                      imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData);
00620 //              }
00621 //              else
00622 //              {
00623 //                      imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData);
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                 // now apply step function
00651                 // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f;
00652 
00653                 if (clothing_weights)
00654                 {
00655                         clothing_weights[vertIndex].mV[VW] = mWeights[index];
00656                 }
00657         }
00658         mWeightsGenerated = TRUE;
00659 }
00660 
00661 //-----------------------------------------------------------------------------
00662 // getMaskForMorphIndex()
00663 //-----------------------------------------------------------------------------
00664 F32* LLPolyVertexMask::getMorphMaskWeights()
00665 {
00666         if (!mWeightsGenerated)
00667         {
00668                 return NULL;
00669         }
00670         
00671         return mWeights;
00672 }

Generated on Thu Jul 1 06:09:01 2010 for Second Life Viewer by  doxygen 1.4.7