llpolymorph.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:20k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpolymorph.cpp
  3.  * @brief Implementation of LLPolyMesh class
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. //-----------------------------------------------------------------------------
  33. // Header Files
  34. //-----------------------------------------------------------------------------
  35. #include "llviewerprecompiledheaders.h"
  36. #include "llpolymorph.h"
  37. #include "llvoavatar.h"
  38. #include "llwearable.h"
  39. #include "llxmltree.h"
  40. #include "llendianswizzle.h"
  41. //#include "../tools/imdebug/imdebug.h"
  42. const F32 NORMAL_SOFTEN_FACTOR = 0.65f;
  43. //-----------------------------------------------------------------------------
  44. // LLPolyMorphData()
  45. //-----------------------------------------------------------------------------
  46. LLPolyMorphData::LLPolyMorphData(const std::string& morph_name)
  47. : mName(morph_name)
  48. {
  49. mNumIndices = 0;
  50. mCurrentIndex = 0;
  51. mTotalDistortion = 0.f;
  52. mAvgDistortion.zeroVec();
  53. mMaxDistortion = 0.f;
  54. mVertexIndices = NULL;
  55. mCoords = NULL;
  56. mNormals = NULL;
  57. mBinormals = NULL;
  58. mTexCoords = NULL;
  59. mMesh = NULL;
  60. }
  61. //-----------------------------------------------------------------------------
  62. // ~LLPolyMorphData()
  63. //-----------------------------------------------------------------------------
  64. LLPolyMorphData::~LLPolyMorphData()
  65. {
  66. delete [] mVertexIndices;
  67. delete [] mCoords;
  68. delete [] mNormals;
  69. delete [] mBinormals;
  70. delete [] mTexCoords;
  71. }
  72. //-----------------------------------------------------------------------------
  73. // loadBinary()
  74. //-----------------------------------------------------------------------------
  75. BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh)
  76. {
  77. S32 numVertices;
  78. S32 numRead;
  79. numRead = fread(&numVertices, sizeof(S32), 1, fp);
  80. llendianswizzle(&numVertices, sizeof(S32), 1);
  81. if (numRead != 1)
  82. {
  83. llwarns << "Can't read number of morph target vertices" << llendl;
  84. return FALSE;
  85. }
  86. //-------------------------------------------------------------------------
  87. // allocate vertices
  88. //-------------------------------------------------------------------------
  89. mCoords = new LLVector3[numVertices];
  90. mNormals = new LLVector3[numVertices];
  91. mBinormals = new LLVector3[numVertices];
  92. mTexCoords = new LLVector2[numVertices];
  93. // Actually, we are allocating more space than we need for the skiplist
  94. mVertexIndices = new U32[numVertices];
  95. mNumIndices = 0;
  96. mTotalDistortion = 0.f;
  97. mMaxDistortion = 0.f;
  98. mAvgDistortion.zeroVec();
  99. mMesh = mesh;
  100. //-------------------------------------------------------------------------
  101. // read vertices
  102. //-------------------------------------------------------------------------
  103. for(S32 v = 0; v < numVertices; v++)
  104. {
  105. numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp);
  106. llendianswizzle(&mVertexIndices[v], sizeof(U32), 1);
  107. if (numRead != 1)
  108. {
  109. llwarns << "Can't read morph target vertex number" << llendl;
  110. return FALSE;
  111. }
  112. if (mVertexIndices[v] > 10000)
  113. {
  114. llerrs << "Bad morph index: " << mVertexIndices[v] << llendl;
  115. }
  116. numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp);
  117. llendianswizzle(&mCoords[v].mV, sizeof(F32), 3);
  118. if (numRead != 3)
  119. {
  120. llwarns << "Can't read morph target vertex coordinates" << llendl;
  121. return FALSE;
  122. }
  123. F32 magnitude = mCoords[v].magVec();
  124. mTotalDistortion += magnitude;
  125. mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]);
  126. mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]);
  127. mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]);
  128. if (magnitude > mMaxDistortion)
  129. {
  130. mMaxDistortion = magnitude;
  131. }
  132. numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp);
  133. llendianswizzle(&mNormals[v].mV, sizeof(F32), 3);
  134. if (numRead != 3)
  135. {
  136. llwarns << "Can't read morph target normal" << llendl;
  137. return FALSE;
  138. }
  139. numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp);
  140. llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3);
  141. if (numRead != 3)
  142. {
  143. llwarns << "Can't read morph target binormal" << llendl;
  144. return FALSE;
  145. }
  146. numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp);
  147. llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2);
  148. if (numRead != 2)
  149. {
  150. llwarns << "Can't read morph target uv" << llendl;
  151. return FALSE;
  152. }
  153. mNumIndices++;
  154. }
  155. mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices);
  156. mAvgDistortion.normVec();
  157. return TRUE;
  158. }
  159. //-----------------------------------------------------------------------------
  160. // LLPolyMorphTargetInfo()
  161. //-----------------------------------------------------------------------------
  162. LLPolyMorphTargetInfo::LLPolyMorphTargetInfo()
  163. : mIsClothingMorph(FALSE)
  164. {
  165. }
  166. BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node)
  167. {
  168. llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) );
  169. if (!LLViewerVisualParamInfo::parseXml(node))
  170. return FALSE;
  171. // Get mixed-case name
  172. static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
  173. if( !node->getFastAttributeString( name_string, mMorphName ) )
  174. {
  175. llwarns << "Avatar file: <param> is missing name attribute" << llendl;
  176. return FALSE;  // Continue, ignoring this tag
  177. }
  178. static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph");
  179. node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph);
  180. LLXmlTreeNode *paramNode = node->getChildByName("param_morph");
  181.         if (NULL == paramNode)
  182.         {
  183.                 llwarns << "Failed to getChildByName("param_morph")"
  184.                         << llendl;
  185.                 return FALSE;
  186.         }
  187. for (LLXmlTreeNode* child_node = paramNode->getFirstChild();
  188.  child_node;
  189.  child_node = paramNode->getNextChild())
  190. {
  191. static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
  192. if (child_node->hasName("volume_morph"))
  193. {
  194. std::string volume_name;
  195. if (child_node->getFastAttributeString(name_string, volume_name))
  196. {
  197. LLVector3 scale;
  198. static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
  199. child_node->getFastAttributeVector3(scale_string, scale);
  200. LLVector3 pos;
  201. static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
  202. child_node->getFastAttributeVector3(pos_string, pos);
  203. mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos));
  204. }
  205. }
  206. }
  207. return TRUE;
  208. }
  209. //-----------------------------------------------------------------------------
  210. // LLPolyMorphTarget()
  211. //-----------------------------------------------------------------------------
  212. LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh)
  213. : mMorphData(NULL), mMesh(poly_mesh),
  214.   mVertMask(NULL),
  215.   mLastSex(SEX_FEMALE),
  216.   mNumMorphMasksPending(0)
  217. {
  218. }
  219. //-----------------------------------------------------------------------------
  220. // ~LLPolyMorphTarget()
  221. //-----------------------------------------------------------------------------
  222. LLPolyMorphTarget::~LLPolyMorphTarget()
  223. {
  224. if (mVertMask)
  225. {
  226. delete mVertMask;
  227. }
  228. }
  229. //-----------------------------------------------------------------------------
  230. // setInfo()
  231. //-----------------------------------------------------------------------------
  232. BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
  233. {
  234. llassert(mInfo == NULL);
  235. if (info->mID < 0)
  236. return FALSE;
  237. mInfo = info;
  238. mID = info->mID;
  239. setWeight(getDefaultWeight(), FALSE );
  240. LLVOAvatar* avatarp = mMesh->getAvatar();
  241. LLPolyMorphTargetInfo::volume_info_list_t::iterator iter;
  242. for (iter = getInfo()->mVolumeInfoList.begin(); iter != getInfo()->mVolumeInfoList.end(); iter++)
  243. {
  244. LLPolyVolumeMorphInfo *volume_info = &(*iter);
  245. for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++)
  246. {
  247. if (avatarp->mCollisionVolumes[i].getName() == volume_info->mName)
  248. {
  249. mVolumeMorphs.push_back(LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i],
  250.   volume_info->mScale,
  251.   volume_info->mPos));
  252. break;
  253. }
  254. }
  255. }
  256. mMorphData = mMesh->getMorphData(getInfo()->mMorphName);
  257. if (!mMorphData)
  258. {
  259. llwarns << "No morph target named " << getInfo()->mMorphName << " found in mesh." << llendl;
  260. return FALSE;  // Continue, ignoring this tag
  261. }
  262. return TRUE;
  263. }
  264. /*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const
  265. {
  266. LLPolyMorphTarget *new_param = new LLPolyMorphTarget(mMesh);
  267. *new_param = *this;
  268. return new_param;
  269. }
  270. #if 0 // obsolete
  271. //-----------------------------------------------------------------------------
  272. // parseData()
  273. //-----------------------------------------------------------------------------
  274. BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node)
  275. {
  276. LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo;
  277. info->parseXml(node);
  278. if (!setInfo(info))
  279. {
  280. delete info;
  281. return FALSE;
  282. }
  283. return TRUE;
  284. }
  285. #endif
  286. //-----------------------------------------------------------------------------
  287. // getVertexDistortion()
  288. //-----------------------------------------------------------------------------
  289. LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh)
  290. {
  291. if (!mMorphData || mMesh != mesh) return LLVector3::zero;
  292. for(U32 index = 0; index < mMorphData->mNumIndices; index++)
  293. {
  294. if (mMorphData->mVertexIndices[index] == (U32)requested_index)
  295. {
  296. return mMorphData->mCoords[index];
  297. }
  298. }
  299. return LLVector3::zero;
  300. }
  301. //-----------------------------------------------------------------------------
  302. // getFirstDistortion()
  303. //-----------------------------------------------------------------------------
  304. const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
  305. {
  306. if (!mMorphData) return &LLVector3::zero;
  307. LLVector3* resultVec;
  308. mMorphData->mCurrentIndex = 0;
  309. if (mMorphData->mNumIndices)
  310. {
  311. resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
  312. if (index != NULL)
  313. {
  314. *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
  315. }
  316. if (poly_mesh != NULL)
  317. {
  318. *poly_mesh = mMesh;
  319. }
  320. return resultVec;
  321. }
  322. return NULL;
  323. }
  324. //-----------------------------------------------------------------------------
  325. // getNextDistortion()
  326. //-----------------------------------------------------------------------------
  327. const LLVector3 *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
  328. {
  329. if (!mMorphData) return &LLVector3::zero;
  330. LLVector3* resultVec;
  331. mMorphData->mCurrentIndex++;
  332. if (mMorphData->mCurrentIndex < mMorphData->mNumIndices)
  333. {
  334. resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex];
  335. if (index != NULL)
  336. {
  337. *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex];
  338. }
  339. if (poly_mesh != NULL)
  340. {
  341. *poly_mesh = mMesh;
  342. }
  343. return resultVec;
  344. }
  345. return NULL;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // getTotalDistortion()
  349. //-----------------------------------------------------------------------------
  350. F32 LLPolyMorphTarget::getTotalDistortion() 
  351. if (mMorphData) 
  352. {
  353. return mMorphData->mTotalDistortion; 
  354. }
  355. else 
  356. {
  357. return 0.f;
  358. }
  359. }
  360. //-----------------------------------------------------------------------------
  361. // getAvgDistortion()
  362. //-----------------------------------------------------------------------------
  363. const LLVector3& LLPolyMorphTarget::getAvgDistortion()
  364. {
  365. if (mMorphData) 
  366. {
  367. return mMorphData->mAvgDistortion; 
  368. }
  369. else 
  370. {
  371. return LLVector3::zero;
  372. }
  373. }
  374. //-----------------------------------------------------------------------------
  375. // getMaxDistortion()
  376. //-----------------------------------------------------------------------------
  377. F32 LLPolyMorphTarget::getMaxDistortion() 
  378. {
  379. if (mMorphData) 
  380. {
  381. return mMorphData->mMaxDistortion; 
  382. }
  383. else
  384. {
  385. return 0.f;
  386. }
  387. }
  388. //-----------------------------------------------------------------------------
  389. // apply()
  390. //-----------------------------------------------------------------------------
  391. void LLPolyMorphTarget::apply( ESex avatar_sex )
  392. {
  393. if (!mMorphData || mNumMorphMasksPending > 0)
  394. {
  395. return;
  396. }
  397. mLastSex = avatar_sex;
  398. // perform differential update of morph
  399. F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
  400. // store last weight
  401. mLastWeight += delta_weight;
  402. if (delta_weight != 0.f)
  403. {
  404. llassert(!mMesh->isLOD());
  405. LLVector3 *coords = mMesh->getWritableCoords();
  406. LLVector3 *scaled_normals = mMesh->getScaledNormals();
  407. LLVector3 *normals = mMesh->getWritableNormals();
  408. LLVector3 *scaled_binormals = mMesh->getScaledBinormals();
  409. LLVector3 *binormals = mMesh->getWritableBinormals();
  410. LLVector4 *clothing_weights = mMesh->getWritableClothingWeights();
  411. LLVector2 *tex_coords = mMesh->getWritableTexCoords();
  412. F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
  413. for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++)
  414. {
  415. S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph];
  416. F32 maskWeight = 1.f;
  417. if (maskWeightArray)
  418. {
  419. maskWeight = maskWeightArray[vert_index_morph];
  420. }
  421. coords[vert_index_mesh] += mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight;
  422. if (getInfo()->mIsClothingMorph && clothing_weights)
  423. {
  424. LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight;
  425. LLVector4* clothing_weight = &clothing_weights[vert_index_mesh];
  426. clothing_weight->mV[VX] += clothing_offset.mV[VX];
  427. clothing_weight->mV[VY] += clothing_offset.mV[VY];
  428. clothing_weight->mV[VZ] += clothing_offset.mV[VZ];
  429. clothing_weight->mV[VW] = maskWeight;
  430. }
  431. // calculate new normals based on half angles
  432. scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
  433. LLVector3 normalized_normal = scaled_normals[vert_index_mesh];
  434. normalized_normal.normVec();
  435. normals[vert_index_mesh] = normalized_normal;
  436. // calculate new binormals
  437. scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR;
  438. LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal;
  439. LLVector3 normalized_binormal = normalized_normal % tangent; 
  440. normalized_binormal.normVec();
  441. binormals[vert_index_mesh] = normalized_binormal;
  442. tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight;
  443. }
  444. // now apply volume changes
  445. for( volume_list_t::iterator iter = mVolumeMorphs.begin(); iter != mVolumeMorphs.end(); iter++ )
  446. {
  447. LLPolyVolumeMorph* volume_morph = &(*iter);
  448. LLVector3 scale_delta = volume_morph->mScale * delta_weight;
  449. LLVector3 pos_delta = volume_morph->mPos * delta_weight;
  450. volume_morph->mVolume->setScale(volume_morph->mVolume->getScale() + scale_delta);
  451. volume_morph->mVolume->setPosition(volume_morph->mVolume->getPosition() + pos_delta);
  452. }
  453. }
  454. if (mNext)
  455. {
  456. mNext->apply(avatar_sex);
  457. }
  458. }
  459. //-----------------------------------------------------------------------------
  460. // applyMask()
  461. //-----------------------------------------------------------------------------
  462. void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
  463. {
  464. LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL;
  465. if (!mVertMask)
  466. {
  467. mVertMask = new LLPolyVertexMask(mMorphData);
  468. mNumMorphMasksPending--;
  469. }
  470. else
  471. {
  472. // remove effect of previous mask
  473. F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL;
  474. if (maskWeights)
  475. {
  476. LLVector3 *coords = mMesh->getWritableCoords();
  477. LLVector3 *scaled_normals = mMesh->getScaledNormals();
  478. LLVector3 *scaled_binormals = mMesh->getScaledBinormals();
  479. LLVector2 *tex_coords = mMesh->getWritableTexCoords();
  480. for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++)
  481. {
  482. F32 lastMaskWeight = mLastWeight * maskWeights[vert];
  483. S32 out_vert = mMorphData->mVertexIndices[vert];
  484. // remove effect of existing masked morph
  485. coords[out_vert] -= mMorphData->mCoords[vert] * lastMaskWeight;
  486. scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR;
  487. scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR;
  488. tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight;
  489. if (clothing_weights)
  490. {
  491. LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight;
  492. LLVector4* clothing_weight = &clothing_weights[out_vert];
  493. clothing_weight->mV[VX] -= clothing_offset.mV[VX];
  494. clothing_weight->mV[VY] -= clothing_offset.mV[VY];
  495. clothing_weight->mV[VZ] -= clothing_offset.mV[VZ];
  496. }
  497. }
  498. }
  499. }
  500. // set last weight to 0, since we've removed the effect of this morph
  501. mLastWeight = 0.f;
  502. mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights);
  503. apply(mLastSex);
  504. }
  505. //-----------------------------------------------------------------------------
  506. // LLPolyVertexMask()
  507. //-----------------------------------------------------------------------------
  508. LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data)
  509. {
  510. mWeights = new F32[morph_data->mNumIndices];
  511. mMorphData = morph_data;
  512. mWeightsGenerated = FALSE;
  513. }
  514. //-----------------------------------------------------------------------------
  515. // ~LLPolyVertexMask()
  516. //-----------------------------------------------------------------------------
  517. LLPolyVertexMask::~LLPolyVertexMask()
  518. {
  519. delete[] mWeights;
  520. }
  521. //-----------------------------------------------------------------------------
  522. // generateMask()
  523. //-----------------------------------------------------------------------------
  524. void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights)
  525. {
  526. // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
  527. // BOOL debugImg = FALSE; 
  528. // if (debugImg)
  529. // {
  530. // if (invert)
  531. // {
  532. // imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData);
  533. // }
  534. // else
  535. // {
  536. // imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData);
  537. // }
  538. // }
  539. for (U32 index = 0; index < mMorphData->mNumIndices; index++)
  540. {
  541. S32 vertIndex = mMorphData->mVertexIndices[index];
  542. const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex);
  543. LLVector2 uvCoords;
  544. if (sharedVertIndex)
  545. {
  546. uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex);
  547. }
  548. else
  549. {
  550. uvCoords = mMorphData->mMesh->getUVs(vertIndex);
  551. }
  552. U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1);
  553. U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1);
  554. mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f;
  555. if (invert) 
  556. {
  557. mWeights[index] = 1.f - mWeights[index];
  558. }
  559. // now apply step function
  560. // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f;
  561. if (clothing_weights)
  562. {
  563. clothing_weights[vertIndex].mV[VW] = mWeights[index];
  564. }
  565. }
  566. mWeightsGenerated = TRUE;
  567. }
  568. //-----------------------------------------------------------------------------
  569. // getMaskForMorphIndex()
  570. //-----------------------------------------------------------------------------
  571. F32* LLPolyVertexMask::getMorphMaskWeights()
  572. {
  573. if (!mWeightsGenerated)
  574. {
  575. return NULL;
  576. }
  577. return mWeights;
  578. }