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 "llvoavatar.h"
00039 #include "llxmltree.h"
00040 #include "llendianswizzle.h"
00041 
00042 //#include "../tools/imdebug/imdebug.h"
00043 
00044 const F32 NORMAL_SOFTEN_FACTOR = 0.65f;
00045 
00046 //-----------------------------------------------------------------------------
00047 // LLPolyMorphData()
00048 //-----------------------------------------------------------------------------
00049 LLPolyMorphData::LLPolyMorphData(char *morph_name)
00050 {
00051         llassert (morph_name);
00052 
00053         mName = new char[strlen(morph_name) + 1];       /*Flawfinder: ignore*/
00054         strcpy(mName, morph_name);      /*Flawfinder: ignore*/
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 // ~LLPolyMorphData()
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 // loadBinary()
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         // allocate vertices
00101         //-------------------------------------------------------------------------
00102         mCoords = new LLVector3[numVertices];
00103         mNormals = new LLVector3[numVertices];
00104         mBinormals = new LLVector3[numVertices];
00105         mTexCoords = new LLVector2[numVertices];
00106         // Actually, we are allocating more space than we need for the skiplist
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         // read vertices
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 // LLPolyMorphTargetInfo()
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         // Get mixed-case name
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;  // Continue, ignoring this tag
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 // LLPolyMorphTarget()
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 // ~LLPolyMorphTarget()
00261 //-----------------------------------------------------------------------------
00262 LLPolyMorphTarget::~LLPolyMorphTarget()
00263 {
00264         if (mVertMask)
00265         {
00266                 delete mVertMask;
00267         }
00268 }
00269 
00270 //-----------------------------------------------------------------------------
00271 // setInfo()
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;  // Continue, ignoring this tag
00305         }
00306         return TRUE;
00307 }
00308 
00309 #if 0 // obsolete
00310 //-----------------------------------------------------------------------------
00311 // parseData()
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 // getVertexDistortion()
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 // getFirstDistortion()
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 // getNextDistortion()
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 // getTotalDistortion()
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 // getAvgDistortion()
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 // getMaxDistortion()
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 // apply()
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         // perform differential update of morph
00454         F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
00455         // store last weight
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                         // calculate new normals based on half angles
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                         // calculate new binormals
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                 // now apply volume changes
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 // applyMask()
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                 // remove effect of previous mask
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                                 // remove effect of existing masked morph
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         // set last weight to 0, since we've removed the effect of this morph
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 // LLPolyVertexMask()
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 // ~LLPolyVertexMask()
00597 //-----------------------------------------------------------------------------
00598 LLPolyVertexMask::~LLPolyVertexMask()
00599 {
00600         delete[] mWeights;
00601 }
00602 
00603 //-----------------------------------------------------------------------------
00604 // generateMask()
00605 //-----------------------------------------------------------------------------
00606 void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights)
00607 {
00608 // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
00609 //      BOOL debugImg = FALSE; 
00610 //      if (debugImg)
00611 //      {
00612 //              if (invert)
00613 //              {
00614 //                      imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData);
00615 //              }
00616 //              else
00617 //              {
00618 //                      imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData);
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                 // now apply step function
00646                 // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f;
00647 
00648                 if (clothing_weights)
00649                 {
00650                         clothing_weights[vertIndex].mV[VW] = mWeights[index];
00651                 }
00652         }
00653         mWeightsGenerated = TRUE;
00654 }
00655 
00656 //-----------------------------------------------------------------------------
00657 // getMaskForMorphIndex()
00658 //-----------------------------------------------------------------------------
00659 F32* LLPolyVertexMask::getMorphMaskWeights()
00660 {
00661         if (!mWeightsGenerated)
00662         {
00663                 return NULL;
00664         }
00665         
00666         return mWeights;
00667 }

Generated on Fri May 16 08:33:56 2008 for SecondLife by  doxygen 1.5.5