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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewerjointmesh.cpp
  3.  * @brief Implementation of LLViewerJointMesh 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 "imageids.h"
  37. #include "llfasttimer.h"
  38. #include "llrender.h"
  39. #include "llapr.h"
  40. #include "llbox.h"
  41. #include "lldrawable.h"
  42. #include "lldrawpoolavatar.h"
  43. #include "lldrawpoolbump.h"
  44. #include "lldynamictexture.h"
  45. #include "llface.h"
  46. #include "llgldbg.h"
  47. #include "llglheaders.h"
  48. #include "lltexlayer.h"
  49. #include "llviewercamera.h"
  50. #include "llviewercontrol.h"
  51. #include "llviewertexturelist.h"
  52. #include "llviewerjointmesh.h"
  53. #include "llvoavatar.h"
  54. #include "llsky.h"
  55. #include "pipeline.h"
  56. #include "llviewershadermgr.h"
  57. #include "llmath.h"
  58. #include "v4math.h"
  59. #include "m3math.h"
  60. #include "m4math.h"
  61. #if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS
  62. extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
  63. extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
  64. extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
  65. #endif
  66. extern BOOL gRenderForSelect;
  67. static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;
  68. static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |
  69.    LLVertexBuffer::MAP_NORMAL |
  70.    LLVertexBuffer::MAP_TEXCOORD0;
  71. //-----------------------------------------------------------------------------
  72. //-----------------------------------------------------------------------------
  73. // LLViewerJointMesh::LLSkinJoint
  74. //-----------------------------------------------------------------------------
  75. //-----------------------------------------------------------------------------
  76. //-----------------------------------------------------------------------------
  77. // LLSkinJoint
  78. //-----------------------------------------------------------------------------
  79. LLSkinJoint::LLSkinJoint()
  80. {
  81. mJoint       = NULL;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // ~LLSkinJoint
  85. //-----------------------------------------------------------------------------
  86. LLSkinJoint::~LLSkinJoint()
  87. {
  88. mJoint = NULL;
  89. }
  90. //-----------------------------------------------------------------------------
  91. // LLSkinJoint::setupSkinJoint()
  92. //-----------------------------------------------------------------------------
  93. BOOL LLSkinJoint::setupSkinJoint( LLViewerJoint *joint)
  94. {
  95. // find the named joint
  96. mJoint = joint;
  97. if ( !mJoint )
  98. {
  99. llinfos << "Can't find joint" << llendl;
  100. }
  101. // compute the inverse root skin matrix
  102. mRootToJointSkinOffset.clearVec();
  103. LLVector3 rootSkinOffset;
  104. while (joint)
  105. {
  106. rootSkinOffset += joint->getSkinOffset();
  107. joint = (LLViewerJoint*)joint->getParent();
  108. }
  109. mRootToJointSkinOffset = -rootSkinOffset;
  110. mRootToParentJointSkinOffset = mRootToJointSkinOffset;
  111. mRootToParentJointSkinOffset += mJoint->getSkinOffset();
  112. return TRUE;
  113. }
  114. //-----------------------------------------------------------------------------
  115. //-----------------------------------------------------------------------------
  116. // LLViewerJointMesh
  117. //-----------------------------------------------------------------------------
  118. //-----------------------------------------------------------------------------
  119. BOOL LLViewerJointMesh::sPipelineRender = FALSE;
  120. EAvatarRenderPass LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE;
  121. U32 LLViewerJointMesh::sClothingMaskImageName = 0;
  122. LLColor4 LLViewerJointMesh::sClothingInnerColor;
  123. //-----------------------------------------------------------------------------
  124. // LLViewerJointMesh()
  125. //-----------------------------------------------------------------------------
  126. LLViewerJointMesh::LLViewerJointMesh()
  127. :
  128. mTexture( NULL ),
  129. mLayerSet( NULL ),
  130. mTestImageName( 0 ),
  131. mFaceIndexCount(0),
  132. mIsTransparent(FALSE)
  133. {
  134. mColor[0] = 1.0f;
  135. mColor[1] = 1.0f;
  136. mColor[2] = 1.0f;
  137. mColor[3] = 1.0f;
  138. mShiny = 0.0f;
  139. mCullBackFaces = TRUE;
  140. mMesh = NULL;
  141. mNumSkinJoints = 0;
  142. mSkinJoints = NULL;
  143. mFace = NULL;
  144. mMeshID = 0;
  145. mUpdateXform = FALSE;
  146. mValid = FALSE;
  147. }
  148. //-----------------------------------------------------------------------------
  149. // ~LLViewerJointMesh()
  150. // Class Destructor
  151. //-----------------------------------------------------------------------------
  152. LLViewerJointMesh::~LLViewerJointMesh()
  153. {
  154. mMesh = NULL;
  155. mTexture = NULL;
  156. freeSkinData();
  157. }
  158. //-----------------------------------------------------------------------------
  159. // LLViewerJointMesh::allocateSkinData()
  160. //-----------------------------------------------------------------------------
  161. BOOL LLViewerJointMesh::allocateSkinData( U32 numSkinJoints )
  162. {
  163. mSkinJoints = new LLSkinJoint[ numSkinJoints ];
  164. mNumSkinJoints = numSkinJoints;
  165. return TRUE;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // LLViewerJointMesh::freeSkinData()
  169. //-----------------------------------------------------------------------------
  170. void LLViewerJointMesh::freeSkinData()
  171. {
  172. mNumSkinJoints = 0;
  173. delete [] mSkinJoints;
  174. mSkinJoints = NULL;
  175. }
  176. //--------------------------------------------------------------------
  177. // LLViewerJointMesh::getColor()
  178. //--------------------------------------------------------------------
  179. void LLViewerJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha )
  180. {
  181. *red   = mColor[0];
  182. *green = mColor[1];
  183. *blue  = mColor[2];
  184. *alpha = mColor[3];
  185. }
  186. //--------------------------------------------------------------------
  187. // LLViewerJointMesh::setColor()
  188. //--------------------------------------------------------------------
  189. void LLViewerJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha )
  190. {
  191. mColor[0] = red;
  192. mColor[1] = green;
  193. mColor[2] = blue;
  194. mColor[3] = alpha;
  195. }
  196. //--------------------------------------------------------------------
  197. // LLViewerJointMesh::getTexture()
  198. //--------------------------------------------------------------------
  199. //LLViewerTexture *LLViewerJointMesh::getTexture()
  200. //{
  201. // return mTexture;
  202. //}
  203. //--------------------------------------------------------------------
  204. // LLViewerJointMesh::setTexture()
  205. //--------------------------------------------------------------------
  206. void LLViewerJointMesh::setTexture( LLViewerTexture *texture )
  207. {
  208. mTexture = texture;
  209. // texture and dynamic_texture are mutually exclusive
  210. if( texture )
  211. {
  212. mLayerSet = NULL;
  213. //texture->bindTexture(0);
  214. //texture->setClamp(TRUE, TRUE);
  215. }
  216. }
  217. //--------------------------------------------------------------------
  218. // LLViewerJointMesh::setLayerSet()
  219. // Sets the shape texture (takes precedence over normal texture)
  220. //--------------------------------------------------------------------
  221. void LLViewerJointMesh::setLayerSet( LLTexLayerSet* layer_set )
  222. {
  223. mLayerSet = layer_set;
  224. // texture and dynamic_texture are mutually exclusive
  225. if( layer_set )
  226. {
  227. mTexture = NULL;
  228. }
  229. }
  230. //--------------------------------------------------------------------
  231. // LLViewerJointMesh::getMesh()
  232. //--------------------------------------------------------------------
  233. LLPolyMesh *LLViewerJointMesh::getMesh()
  234. {
  235. return mMesh;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // LLViewerJointMesh::setMesh()
  239. //-----------------------------------------------------------------------------
  240. void LLViewerJointMesh::setMesh( LLPolyMesh *mesh )
  241. {
  242. // set the mesh pointer
  243. mMesh = mesh;
  244. // release any existing skin joints
  245. freeSkinData();
  246. if ( mMesh == NULL )
  247. {
  248. return;
  249. }
  250. // acquire the transform from the mesh object
  251. setPosition( mMesh->getPosition() );
  252. setRotation( mMesh->getRotation() );
  253. setScale( mMesh->getScale() );
  254. // create skin joints if necessary
  255. if ( mMesh->hasWeights() && !mMesh->isLOD())
  256. {
  257. U32 numJointNames = mMesh->getNumJointNames();
  258. allocateSkinData( numJointNames );
  259. std::string *jointNames = mMesh->getJointNames();
  260. U32 jn;
  261. for (jn = 0; jn < numJointNames; jn++)
  262. {
  263. //llinfos << "Setting up joint " << jointNames[jn] << llendl;
  264. LLViewerJoint* joint = (LLViewerJoint*)(getRoot()->findJoint(jointNames[jn]) );
  265. mSkinJoints[jn].setupSkinJoint( joint );
  266. }
  267. }
  268. // setup joint array
  269. if (!mMesh->isLOD())
  270. {
  271. setupJoint((LLViewerJoint*)getRoot());
  272. }
  273. // llinfos << "joint render entries: " << mMesh->mJointRenderData.count() << llendl;
  274. }
  275. //-----------------------------------------------------------------------------
  276. // setupJoint()
  277. //-----------------------------------------------------------------------------
  278. void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint)
  279. {
  280. // llinfos << "Mesh: " << getName() << llendl;
  281. // S32 joint_count = 0;
  282. U32 sj;
  283. for (sj=0; sj<mNumSkinJoints; sj++)
  284. {
  285. LLSkinJoint &js = mSkinJoints[sj];
  286. if (js.mJoint != current_joint)
  287. {
  288. continue;
  289. }
  290. // we've found a skinjoint for this joint..
  291. // is the last joint in the array our parent?
  292. if(mMesh->mJointRenderData.count() && mMesh->mJointRenderData[mMesh->mJointRenderData.count() - 1]->mWorldMatrix == &current_joint->getParent()->getWorldMatrix())
  293. {
  294. // ...then just add ourselves
  295. LLViewerJoint* jointp = js.mJoint;
  296. mMesh->mJointRenderData.put(new LLJointRenderData(&jointp->getWorldMatrix(), &js));
  297. // llinfos << "joint " << joint_count << js.mJoint->getName() << llendl;
  298. // joint_count++;
  299. }
  300. // otherwise add our parent and ourselves
  301. else
  302. {
  303. mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getParent()->getWorldMatrix(), NULL));
  304. // llinfos << "joint " << joint_count << current_joint->getParent()->getName() << llendl;
  305. // joint_count++;
  306. mMesh->mJointRenderData.put(new LLJointRenderData(&current_joint->getWorldMatrix(), &js));
  307. // llinfos << "joint " << joint_count << current_joint->getName() << llendl;
  308. // joint_count++;
  309. }
  310. }
  311. // depth-first traversal
  312. for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
  313.  iter != current_joint->mChildren.end(); ++iter)
  314. {
  315. LLViewerJoint* child_joint = (LLViewerJoint*)(*iter);
  316. setupJoint(child_joint);
  317. }
  318. }
  319. const S32 NUM_AXES = 3;
  320. // register layoud
  321. // rotation X 0-n
  322. // rotation Y 0-n
  323. // rotation Z 0-n
  324. // pivot parent 0-n -- child = n+1
  325. static LLMatrix4 gJointMatUnaligned[32];
  326. static LLMatrix3 gJointRotUnaligned[32];
  327. static LLVector4 gJointPivot[32];
  328. //-----------------------------------------------------------------------------
  329. // uploadJointMatrices()
  330. //-----------------------------------------------------------------------------
  331. void LLViewerJointMesh::uploadJointMatrices()
  332. {
  333. S32 joint_num;
  334. LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
  335. LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
  336. BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
  337. //calculate joint matrices
  338. for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
  339. {
  340. LLMatrix4 joint_mat = *reference_mesh->mJointRenderData[joint_num]->mWorldMatrix;
  341. if (hardware_skinning)
  342. {
  343. joint_mat *= LLDrawPoolAvatar::getModelView();
  344. }
  345. gJointMatUnaligned[joint_num] = joint_mat;
  346. gJointRotUnaligned[joint_num] = joint_mat.getMat3();
  347. }
  348. BOOL last_pivot_uploaded = FALSE;
  349. S32 j = 0;
  350. //upload joint pivots
  351. for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
  352. {
  353. LLSkinJoint *sj = reference_mesh->mJointRenderData[joint_num]->mSkinJoint;
  354. if (sj)
  355. {
  356. if (!last_pivot_uploaded)
  357. {
  358. LLVector4 parent_pivot(sj->mRootToParentJointSkinOffset);
  359. parent_pivot.mV[VW] = 0.f;
  360. gJointPivot[j++] = parent_pivot;
  361. }
  362. LLVector4 child_pivot(sj->mRootToJointSkinOffset);
  363. child_pivot.mV[VW] = 0.f;
  364. gJointPivot[j++] = child_pivot;
  365. last_pivot_uploaded = TRUE;
  366. }
  367. else
  368. {
  369. last_pivot_uploaded = FALSE;
  370. }
  371. }
  372. //add pivot point into transform
  373. for (S32 i = 0; i < j; i++)
  374. {
  375. LLVector3 pivot;
  376. pivot = LLVector3(gJointPivot[i]);
  377. pivot = pivot * gJointRotUnaligned[i];
  378. gJointMatUnaligned[i].translate(pivot);
  379. }
  380. // upload matrices
  381. if (hardware_skinning)
  382. {
  383. GLfloat mat[45*4];
  384. memset(mat, 0, sizeof(GLfloat)*45*4);
  385. for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); joint_num++)
  386. {
  387. gJointMatUnaligned[joint_num].transpose();
  388. for (S32 axis = 0; axis < NUM_AXES; axis++)
  389. {
  390. F32* vector = gJointMatUnaligned[joint_num].mMatrix[axis];
  391. U32 offset = LL_CHARACTER_MAX_JOINTS_PER_MESH*axis+joint_num;
  392. memcpy(mat+offset*4, vector, sizeof(GLfloat)*4);
  393. }
  394. }
  395. stop_glerror();
  396. glUniform4fvARB(gAvatarMatrixParam, 45, mat);
  397. stop_glerror();
  398. }
  399. }
  400. //--------------------------------------------------------------------
  401. // LLViewerJointMesh::drawBone()
  402. //--------------------------------------------------------------------
  403. void LLViewerJointMesh::drawBone()
  404. {
  405. }
  406. //--------------------------------------------------------------------
  407. // LLViewerJointMesh::isTransparent()
  408. //--------------------------------------------------------------------
  409. BOOL LLViewerJointMesh::isTransparent()
  410. {
  411. return mIsTransparent;
  412. }
  413. //--------------------------------------------------------------------
  414. // DrawElementsBLEND and utility code
  415. //--------------------------------------------------------------------
  416. // compate_int is used by the qsort function to sort the index array
  417. int compare_int(const void *a, const void *b)
  418. {
  419. if (*(U32*)a < *(U32*)b)
  420. {
  421. return -1;
  422. }
  423. else if (*(U32*)a > *(U32*)b)
  424. {
  425. return 1;
  426. }
  427. else return 0;
  428. }
  429. //--------------------------------------------------------------------
  430. // LLViewerJointMesh::drawShape()
  431. //--------------------------------------------------------------------
  432. U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
  433. {
  434. if (!mValid || !mMesh || !mFace || !mVisible || 
  435. mFace->mVertexBuffer.isNull() ||
  436. mMesh->getNumFaces() == 0) 
  437. {
  438. return 0;
  439. }
  440. U32 triangle_count = 0;
  441. stop_glerror();
  442. //----------------------------------------------------------------
  443. // setup current color
  444. //----------------------------------------------------------------
  445. if (!gRenderForSelect)
  446. {
  447. if (is_dummy)
  448. glColor4fv(LLVOAvatar::getDummyColor().mV);
  449. else
  450. glColor4fv(mColor.mV);
  451. }
  452. stop_glerror();
  453. LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0));
  454. //----------------------------------------------------------------
  455. // setup current texture
  456. //----------------------------------------------------------------
  457. llassert( !(mTexture.notNull() && mLayerSet) );  // mutually exclusive
  458. LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP;
  459. if (mTestImageName)
  460. {
  461. gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName);
  462. if (mIsTransparent)
  463. {
  464. glColor4f(1.f, 1.f, 1.f, 1.f);
  465. }
  466. else
  467. {
  468. glColor4f(0.7f, 0.6f, 0.3f, 1.f);
  469. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
  470. }
  471. }
  472. else if( !is_dummy && mLayerSet )
  473. {
  474. if( mLayerSet->hasComposite() )
  475. {
  476. gGL.getTexUnit(0)->bind(mLayerSet->getComposite());
  477. }
  478. else
  479. {
  480. // This warning will always trigger if you've hacked the avatar to show as incomplete.
  481. // Ignore the warning if that's the case.
  482. if (!gSavedSettings.getBOOL("RenderUnloadedAvatar"))
  483. {
  484. //llwarns << "Layerset without composite" << llendl;
  485. }
  486. gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
  487. }
  488. }
  489. else
  490. if ( !is_dummy && mTexture.notNull() )
  491. {
  492. if(mTexture->hasGLTexture())
  493. {
  494. old_mode = mTexture->getAddressMode();
  495. }
  496. gGL.getTexUnit(0)->bind(mTexture.get());
  497. gGL.getTexUnit(0)->bind(mTexture);
  498. gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
  499. }
  500. else
  501. {
  502. gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
  503. }
  504. if (gRenderForSelect)
  505. {
  506. if (isTransparent())
  507. {
  508. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
  509. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA);
  510. }
  511. else
  512. {
  513. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  514. }
  515. }
  516. mFace->mVertexBuffer->setBuffer(sRenderMask);
  517. U32 start = mMesh->mFaceVertexOffset;
  518. U32 end = start + mMesh->mFaceVertexCount - 1;
  519. U32 count = mMesh->mFaceIndexCount;
  520. U32 offset = mMesh->mFaceIndexOffset;
  521. if (mMesh->hasWeights())
  522. {
  523. if ((mFace->getPool()->getVertexShaderLevel() > 0))
  524. {
  525. if (first_pass)
  526. {
  527. uploadJointMatrices();
  528. }
  529. }
  530. mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
  531. }
  532. else
  533. {
  534. glPushMatrix();
  535. LLMatrix4 jointToWorld = getWorldMatrix();
  536. glMultMatrixf((GLfloat*)jointToWorld.mMatrix);
  537. mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
  538. glPopMatrix();
  539. }
  540. gPipeline.addTrianglesDrawn(count/3);
  541. triangle_count += count;
  542. if (mTestImageName)
  543. {
  544. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  545. }
  546. if (mTexture.notNull() && !is_dummy)
  547. {
  548. gGL.getTexUnit(0)->bind(mTexture);
  549. gGL.getTexUnit(0)->setTextureAddressMode(old_mode);
  550. }
  551. return triangle_count;
  552. }
  553. //-----------------------------------------------------------------------------
  554. // updateFaceSizes()
  555. //-----------------------------------------------------------------------------
  556. void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
  557. {
  558. // Do a pre-alloc pass to determine sizes of data.
  559. if (mMesh && mValid)
  560. {
  561. mMesh->mFaceVertexOffset = num_vertices;
  562. mMesh->mFaceVertexCount = mMesh->getNumVertices();
  563. mMesh->mFaceIndexOffset = num_indices;
  564. mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices;
  565. mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount;
  566. num_vertices += mMesh->getNumVertices();
  567. num_indices += mMesh->mFaceIndexCount;
  568. }
  569. }
  570. //-----------------------------------------------------------------------------
  571. // updateFaceData()
  572. //-----------------------------------------------------------------------------
  573. void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind)
  574. {
  575. mFace = face;
  576. if (mFace->mVertexBuffer.isNull())
  577. {
  578. return;
  579. }
  580. LLStrider<LLVector3> verticesp;
  581. LLStrider<LLVector3> normalsp;
  582. LLStrider<LLVector2> tex_coordsp;
  583. LLStrider<F32>  vertex_weightsp;
  584. LLStrider<LLVector4> clothing_weightsp;
  585. LLStrider<U16> indicesp;
  586. // Copy data into the faces from the polymesh data.
  587. if (mMesh && mValid)
  588. {
  589. if (mMesh->getNumVertices())
  590. {
  591. stop_glerror();
  592. face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp);
  593. stop_glerror();
  594. face->mVertexBuffer->getIndexStrider(indicesp);
  595. stop_glerror();
  596. for (U16 i = 0; i < mMesh->getNumVertices(); i++)
  597. {
  598. verticesp[mMesh->mFaceVertexOffset + i] = *(mMesh->getCoords() + i);
  599. tex_coordsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getTexCoords() + i);
  600. normalsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getNormals() + i);
  601. vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i);
  602. if (damp_wind)
  603. {
  604. clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0);
  605. }
  606. else
  607. {
  608. clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i));
  609. }
  610. }
  611. for (S32 i = 0; i < mMesh->getNumFaces(); i++)
  612. {
  613. for (U32 j = 0; j < 3; j++)
  614. {
  615. U32 k = i*3+j+mMesh->mFaceIndexOffset;
  616. indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset;
  617. }
  618. }
  619. }
  620. }
  621. }
  622. //-----------------------------------------------------------------------------
  623. // updateLOD()
  624. //-----------------------------------------------------------------------------
  625. BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate)
  626. {
  627. BOOL valid = mValid;
  628. setValid(activate, TRUE);
  629. return (valid != activate);
  630. }
  631. // static
  632. void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh)
  633. {
  634. LLStrider<LLVector3> o_vertices;
  635. LLStrider<LLVector3> o_normals;
  636. //get vertex and normal striders
  637. LLVertexBuffer *buffer = mFace->mVertexBuffer;
  638. buffer->getVertexStrider(o_vertices,  0);
  639. buffer->getNormalStrider(o_normals,   0);
  640. F32 last_weight = F32_MAX;
  641. LLMatrix4 gBlendMat;
  642. LLMatrix3 gBlendRotMat;
  643. const F32* weights = mMesh->getWeights();
  644. const LLVector3* coords = mMesh->getCoords();
  645. const LLVector3* normals = mMesh->getNormals();
  646. for (U32 index = 0; index < mMesh->getNumVertices(); index++)
  647. {
  648. U32 bidx = index + mMesh->mFaceVertexOffset;
  649. // blend by first matrix
  650. F32 w = weights[index]; 
  651. // Maybe we don't have to change gBlendMat.
  652. // Profiles of a single-avatar scene on a Mac show this to be a very
  653. // common case.  JC
  654. if (w == last_weight)
  655. {
  656. o_vertices[bidx] = coords[index] * gBlendMat;
  657. o_normals[bidx] = normals[index] * gBlendRotMat;
  658. continue;
  659. }
  660. last_weight = w;
  661. S32 joint = llfloor(w);
  662. w -= joint;
  663. // No lerp required in this case.
  664. if (w == 1.0f)
  665. {
  666. gBlendMat = gJointMatUnaligned[joint+1];
  667. o_vertices[bidx] = coords[index] * gBlendMat;
  668. gBlendRotMat = gJointRotUnaligned[joint+1];
  669. o_normals[bidx] = normals[index] * gBlendRotMat;
  670. continue;
  671. }
  672. // Try to keep all the accesses to the matrix data as close
  673. // together as possible.  This function is a hot spot on the
  674. // Mac. JC
  675. LLMatrix4 &m0 = gJointMatUnaligned[joint+1];
  676. LLMatrix4 &m1 = gJointMatUnaligned[joint+0];
  677. gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w);
  678. gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w);
  679. gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w);
  680. gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w);
  681. gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w);
  682. gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w);
  683. gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w);
  684. gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w);
  685. gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w);
  686. gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w);
  687. gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w);
  688. gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w);
  689. o_vertices[bidx] = coords[index] * gBlendMat;
  690. LLMatrix3 &n0 = gJointRotUnaligned[joint+1];
  691. LLMatrix3 &n1 = gJointRotUnaligned[joint+0];
  692. gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w);
  693. gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w);
  694. gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w);
  695. gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w);
  696. gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w);
  697. gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w);
  698. gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w);
  699. gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w);
  700. gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w);
  701. o_normals[bidx] = normals[index] * gBlendRotMat;
  702. }
  703. buffer->setBuffer(0);
  704. }
  705. const U32 UPDATE_GEOMETRY_CALL_MASK = 0x1FFF; // 8K samples before overflow
  706. const U32 UPDATE_GEOMETRY_CALL_OVERFLOW = ~UPDATE_GEOMETRY_CALL_MASK;
  707. static bool sUpdateGeometryCallPointer = false;
  708. static F64 sUpdateGeometryGlobalTime = 0.0 ;
  709. static F64 sUpdateGeometryElapsedTime = 0.0 ;
  710. static F64 sUpdateGeometryElapsedTimeOff = 0.0 ;
  711. static F64 sUpdateGeometryElapsedTimeOn = 0.0 ;
  712. static F64 sUpdateGeometryRunAvgOff[10];
  713. static F64 sUpdateGeometryRunAvgOn[10];
  714. static U32 sUpdateGeometryRunCount = 0 ;
  715. static U32 sUpdateGeometryCalls = 0 ;
  716. static U32 sUpdateGeometryLastProcessor = 0 ;
  717. static BOOL sVectorizePerfTest  = FALSE;
  718. static U32 sVectorizeProcessor  = 0;
  719. //static
  720. void (*LLViewerJointMesh::sUpdateGeometryFunc)(LLFace* face, LLPolyMesh* mesh);
  721. //static
  722. void LLViewerJointMesh::updateVectorize()
  723. {
  724. sVectorizePerfTest = gSavedSettings.getBOOL("VectorizePerfTest");
  725. sVectorizeProcessor = gSavedSettings.getU32("VectorizeProcessor");
  726. BOOL vectorizeEnable = gSavedSettings.getBOOL("VectorizeEnable");
  727. BOOL vectorizeSkin = gSavedSettings.getBOOL("VectorizeSkin");
  728. std::string vp;
  729. switch(sVectorizeProcessor)
  730. {
  731. case 2: vp = "SSE2"; break; // *TODO: replace the magic #s
  732. case 1: vp = "SSE"; break;
  733. default: vp = "COMPILER DEFAULT"; break;
  734. }
  735. LL_INFOS("AppInit") << "Vectorization         : " << ( vectorizeEnable ? "ENABLED" : "DISABLED" ) << LL_ENDL ;
  736. LL_INFOS("AppInit") << "Vector Processor      : " << vp << LL_ENDL ;
  737. LL_INFOS("AppInit") << "Vectorized Skinning   : " << ( vectorizeSkin ? "ENABLED" : "DISABLED" ) << LL_ENDL ;
  738. if(vectorizeEnable && vectorizeSkin)
  739. {
  740. switch(sVectorizeProcessor)
  741. {
  742. case 2:
  743. sUpdateGeometryFunc = &updateGeometrySSE2;
  744. break;
  745. case 1:
  746. sUpdateGeometryFunc = &updateGeometrySSE;
  747. break;
  748. default:
  749. sUpdateGeometryFunc = &updateGeometryVectorized;
  750. break;
  751. }
  752. }
  753. else
  754. {
  755. sUpdateGeometryFunc = &updateGeometryOriginal;
  756. }
  757. }
  758. void LLViewerJointMesh::updateJointGeometry()
  759. {
  760. if (!(mValid
  761.   && mMesh
  762.   && mFace
  763.   && mMesh->hasWeights()
  764.   && mFace->mVertexBuffer.notNull()
  765.   && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
  766. {
  767. return;
  768. }
  769. if (!sVectorizePerfTest)
  770. {
  771. // Once we've measured performance, just run the specified
  772. // code version.
  773. if(sUpdateGeometryFunc == updateGeometryOriginal)
  774. uploadJointMatrices();
  775. sUpdateGeometryFunc(mFace, mMesh);
  776. }
  777. else
  778. {
  779. // At startup, measure the amount of time in skinning and choose
  780. // the fastest one.
  781. LLTimer ug_timer ;
  782. if (sUpdateGeometryCallPointer)
  783. {
  784. if(sUpdateGeometryFunc == updateGeometryOriginal)
  785. uploadJointMatrices();
  786. // call accelerated version for this processor
  787. sUpdateGeometryFunc(mFace, mMesh);
  788. }
  789. else
  790. {
  791. uploadJointMatrices();
  792. updateGeometryOriginal(mFace, mMesh);
  793. }
  794. sUpdateGeometryElapsedTime += ug_timer.getElapsedTimeF64();
  795. ++sUpdateGeometryCalls;
  796. if(0 != (sUpdateGeometryCalls & UPDATE_GEOMETRY_CALL_OVERFLOW))
  797. {
  798. F64 time_since_app_start = ug_timer.getElapsedSeconds();
  799. if(sUpdateGeometryGlobalTime == 0.0 
  800. || sUpdateGeometryLastProcessor != sVectorizeProcessor)
  801. {
  802. sUpdateGeometryGlobalTime = time_since_app_start;
  803. sUpdateGeometryElapsedTime = 0;
  804. sUpdateGeometryCalls = 0;
  805. sUpdateGeometryRunCount = 0;
  806. sUpdateGeometryLastProcessor = sVectorizeProcessor;
  807. sUpdateGeometryCallPointer = false;
  808. return;
  809. }
  810. F64 percent_time_in_function = 
  811. ( sUpdateGeometryElapsedTime * 100.0 ) / ( time_since_app_start - sUpdateGeometryGlobalTime ) ;
  812. sUpdateGeometryGlobalTime = time_since_app_start;
  813. if (!sUpdateGeometryCallPointer)
  814. {
  815. // First set of run data is with vectorization off.
  816. sUpdateGeometryCallPointer = true;
  817. llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
  818. << "vectorize off " << percent_time_in_function
  819. << "% of time with "
  820. << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
  821. << " seconds per call "
  822. << llendl;
  823. sUpdateGeometryRunAvgOff[sUpdateGeometryRunCount] = percent_time_in_function;
  824. sUpdateGeometryElapsedTimeOff += sUpdateGeometryElapsedTime;
  825. sUpdateGeometryCalls = 0;
  826. }
  827. else
  828. {
  829. // Second set of run data is with vectorization on.
  830. sUpdateGeometryCallPointer = false;
  831. llinfos << "profile (avg of " << sUpdateGeometryCalls << " samples) = "
  832. << "VEC on " << percent_time_in_function
  833. << "% of time with "
  834. << (sUpdateGeometryElapsedTime / (F64)sUpdateGeometryCalls)
  835. << " seconds per call "
  836. << llendl;
  837. sUpdateGeometryRunAvgOn[sUpdateGeometryRunCount] = percent_time_in_function ;
  838. sUpdateGeometryElapsedTimeOn += sUpdateGeometryElapsedTime;
  839. sUpdateGeometryCalls = 0;
  840. sUpdateGeometryRunCount++;
  841. F64 a = 0.0, b = 0.0;
  842. for(U32 i = 0; i<sUpdateGeometryRunCount; i++)
  843. {
  844. a += sUpdateGeometryRunAvgOff[i];
  845. b += sUpdateGeometryRunAvgOn[i];
  846. }
  847. a /= sUpdateGeometryRunCount;
  848. b /= sUpdateGeometryRunCount;
  849. F64 perf_boost = ( sUpdateGeometryElapsedTimeOff - sUpdateGeometryElapsedTimeOn ) / sUpdateGeometryElapsedTimeOn;
  850. llinfos << "run averages (" << (F64)sUpdateGeometryRunCount
  851. << "/10) vectorize off " << a
  852. << "% : vectorize type " << sVectorizeProcessor
  853. << " " << b
  854. << "% : performance boost " 
  855. << perf_boost * 100.0
  856. << "%"
  857. << llendl ;
  858. if(sUpdateGeometryRunCount == 10)
  859. {
  860. // In case user runs test again, force reset of data on
  861. // next run.
  862. sUpdateGeometryGlobalTime = 0.0;
  863. // We have data now on which version is faster.  Switch to that
  864. // code and save the data for next run.
  865. gSavedSettings.setBOOL("VectorizePerfTest", FALSE);
  866. if (perf_boost > 0.0)
  867. {
  868. llinfos << "Vectorization improves avatar skinning performance, "
  869. << "keeping on for future runs."
  870. << llendl;
  871. gSavedSettings.setBOOL("VectorizeSkin", TRUE);
  872. }
  873. else
  874. {
  875. // SIMD decreases performance, fall back to original code
  876. llinfos << "Vectorization decreases avatar skinning performance, "
  877. << "switching back to original code."
  878. << llendl;
  879. gSavedSettings.setBOOL("VectorizeSkin", FALSE);
  880. }
  881. }
  882. }
  883. sUpdateGeometryElapsedTime = 0.0f;
  884. }
  885. }
  886. }
  887. void LLViewerJointMesh::dump()
  888. {
  889. if (mValid)
  890. {
  891. llinfos << "Usable LOD " << mName << llendl;
  892. }
  893. }
  894. // End