PageRenderTime 45ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llpolymorph.cpp

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