PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llvograss.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 759 lines | 580 code | 139 blank | 40 comment | 65 complexity | 325c7eda420e65d0729684f09b859341 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvograss.cpp
  3. * @brief Not a blade, but a clump of grass
  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. #include "llviewerprecompiledheaders.h"
  27. #include "llvograss.h"
  28. #include "imageids.h"
  29. #include "llviewercontrol.h"
  30. #include "llagentcamera.h"
  31. #include "llnotificationsutil.h"
  32. #include "lldrawable.h"
  33. #include "llface.h"
  34. #include "llsky.h"
  35. #include "llsurface.h"
  36. #include "llsurfacepatch.h"
  37. #include "llvosky.h"
  38. #include "llviewercamera.h"
  39. #include "llviewertexturelist.h"
  40. #include "llviewerregion.h"
  41. #include "pipeline.h"
  42. #include "llspatialpartition.h"
  43. #include "llworld.h"
  44. #include "lldir.h"
  45. #include "llxmltree.h"
  46. #include "llvotree.h"
  47. const S32 GRASS_MAX_BLADES = 32;
  48. const F32 GRASS_BLADE_BASE = 0.25f; // Width of grass at base
  49. const F32 GRASS_BLADE_TOP = 0.25f; // Width of grass at top
  50. const F32 GRASS_BLADE_HEIGHT = 0.5f; // meters
  51. const F32 GRASS_DISTRIBUTION_SD = 0.15f; // empirically defined
  52. F32 exp_x[GRASS_MAX_BLADES];
  53. F32 exp_y[GRASS_MAX_BLADES];
  54. F32 rot_x[GRASS_MAX_BLADES];
  55. F32 rot_y[GRASS_MAX_BLADES];
  56. F32 dz_x [GRASS_MAX_BLADES];
  57. F32 dz_y [GRASS_MAX_BLADES];
  58. F32 w_mod[GRASS_MAX_BLADES]; // Factor to modulate wind movement by to randomize appearance
  59. LLVOGrass::SpeciesMap LLVOGrass::sSpeciesTable;
  60. S32 LLVOGrass::sMaxGrassSpecies = 0;
  61. LLVOGrass::LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
  62. : LLAlphaObject(id, pcode, regionp)
  63. {
  64. mPatch = NULL;
  65. mLastPatchUpdateTime = 0;
  66. mGrassVel.clearVec();
  67. mGrassBend.clearVec();
  68. mbCanSelect = TRUE;
  69. mBladeWindAngle = 35.f;
  70. mBWAOverlap = 2.f;
  71. setNumTEs(1);
  72. setTEColor(0, LLColor4(1.0f, 1.0f, 1.0f, 1.f));
  73. mNumBlades = GRASS_MAX_BLADES;
  74. }
  75. LLVOGrass::~LLVOGrass()
  76. {
  77. }
  78. void LLVOGrass::updateSpecies()
  79. {
  80. mSpecies = mState;
  81. if (!sSpeciesTable.count(mSpecies))
  82. {
  83. llinfos << "Unknown grass type, substituting grass type." << llendl;
  84. SpeciesMap::const_iterator it = sSpeciesTable.begin();
  85. mSpecies = (*it).first;
  86. }
  87. setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
  88. }
  89. void LLVOGrass::initClass()
  90. {
  91. LLVector3 pos(0.0f, 0.0f, 0.0f);
  92. // Create nifty list of exponential distribution 0-1
  93. F32 x = 0.f;
  94. F32 y = 0.f;
  95. F32 rot;
  96. std::string xml_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"grass.xml");
  97. LLXmlTree grass_def_grass;
  98. if (!grass_def_grass.parseFile(xml_filename))
  99. {
  100. llerrs << "Failed to parse grass file." << llendl;
  101. return;
  102. }
  103. LLXmlTreeNode* rootp = grass_def_grass.getRoot();
  104. for (LLXmlTreeNode* grass_def = rootp->getFirstChild();
  105. grass_def;
  106. grass_def = rootp->getNextChild())
  107. {
  108. if (!grass_def->hasName("grass"))
  109. {
  110. llwarns << "Invalid grass definition node " << grass_def->getName() << llendl;
  111. continue;
  112. }
  113. F32 F32_val;
  114. LLUUID id;
  115. BOOL success = TRUE;
  116. S32 species;
  117. static LLStdStringHandle species_id_string = LLXmlTree::addAttributeString("species_id");
  118. if (!grass_def->getFastAttributeS32(species_id_string, species))
  119. {
  120. llwarns << "No species id defined" << llendl;
  121. continue;
  122. }
  123. if (species < 0)
  124. {
  125. llwarns << "Invalid species id " << species << llendl;
  126. continue;
  127. }
  128. GrassSpeciesData* newGrass = new GrassSpeciesData();
  129. static LLStdStringHandle texture_id_string = LLXmlTree::addAttributeString("texture_id");
  130. grass_def->getFastAttributeUUID(texture_id_string, id);
  131. newGrass->mTextureID = id;
  132. static LLStdStringHandle blade_sizex_string = LLXmlTree::addAttributeString("blade_size_x");
  133. success &= grass_def->getFastAttributeF32(blade_sizex_string, F32_val);
  134. newGrass->mBladeSizeX = F32_val;
  135. static LLStdStringHandle blade_sizey_string = LLXmlTree::addAttributeString("blade_size_y");
  136. success &= grass_def->getFastAttributeF32(blade_sizey_string, F32_val);
  137. newGrass->mBladeSizeY = F32_val;
  138. if (sSpeciesTable.count(species))
  139. {
  140. llinfos << "Grass species " << species << " already defined! Duplicate discarded." << llendl;
  141. delete newGrass;
  142. continue;
  143. }
  144. else
  145. {
  146. sSpeciesTable[species] = newGrass;
  147. }
  148. if (species >= sMaxGrassSpecies) sMaxGrassSpecies = species + 1;
  149. if (!success)
  150. {
  151. std::string name;
  152. static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
  153. grass_def->getFastAttributeString(name_string, name);
  154. llwarns << "Incomplete definition of grass " << name << llendl;
  155. }
  156. }
  157. BOOL have_all_grass = TRUE;
  158. std::string err;
  159. for (S32 i=0;i<sMaxGrassSpecies;++i)
  160. {
  161. if (!sSpeciesTable.count(i))
  162. {
  163. err.append(llformat(" %d",i));
  164. have_all_grass = FALSE;
  165. }
  166. }
  167. if (!have_all_grass)
  168. {
  169. LLSD args;
  170. args["SPECIES"] = err;
  171. LLNotificationsUtil::add("ErrorUndefinedGrasses", args);
  172. }
  173. for (S32 i = 0; i < GRASS_MAX_BLADES; ++i)
  174. {
  175. if (1) //(i%2 == 0) Uncomment for X blading
  176. {
  177. F32 u = sqrt(-2.0f * log(ll_frand()));
  178. F32 v = 2.0f * F_PI * ll_frand();
  179. x = u * sin(v) * GRASS_DISTRIBUTION_SD;
  180. y = u * cos(v) * GRASS_DISTRIBUTION_SD;
  181. rot = ll_frand(F_PI);
  182. }
  183. else
  184. {
  185. rot += (F_PI*0.4f + ll_frand(0.2f*F_PI));
  186. }
  187. exp_x[i] = x;
  188. exp_y[i] = y;
  189. rot_x[i] = sin(rot);
  190. rot_y[i] = cos(rot);
  191. dz_x[i] = ll_frand(GRASS_BLADE_BASE * 0.25f);
  192. dz_y[i] = ll_frand(GRASS_BLADE_BASE * 0.25f);
  193. w_mod[i] = 0.5f + ll_frand(); // Degree to which blade is moved by wind
  194. }
  195. }
  196. void LLVOGrass::cleanupClass()
  197. {
  198. for_each(sSpeciesTable.begin(), sSpeciesTable.end(), DeletePairedPointer());
  199. }
  200. U32 LLVOGrass::processUpdateMessage(LLMessageSystem *mesgsys,
  201. void **user_data,
  202. U32 block_num,
  203. const EObjectUpdateType update_type,
  204. LLDataPacker *dp)
  205. {
  206. // Do base class updates...
  207. U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
  208. updateSpecies();
  209. if ( (getVelocity().lengthSquared() > 0.f)
  210. ||(getAcceleration().lengthSquared() > 0.f)
  211. ||(getAngularVelocity().lengthSquared() > 0.f))
  212. {
  213. llinfos << "ACK! Moving grass!" << llendl;
  214. setVelocity(LLVector3::zero);
  215. setAcceleration(LLVector3::zero);
  216. setAngularVelocity(LLVector3::zero);
  217. }
  218. if (mDrawable)
  219. {
  220. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
  221. }
  222. return retval;
  223. }
  224. BOOL LLVOGrass::isActive() const
  225. {
  226. return TRUE;
  227. }
  228. BOOL LLVOGrass::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
  229. {
  230. if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_GRASS)))
  231. {
  232. return TRUE;
  233. }
  234. if (!mDrawable)
  235. {
  236. // So drones work.
  237. return TRUE;
  238. }
  239. if(LLVOTree::isTreeRenderingStopped()) //stop rendering grass
  240. {
  241. if(mNumBlades)
  242. {
  243. mNumBlades = 0 ;
  244. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  245. }
  246. return TRUE ;
  247. }
  248. else if(!mNumBlades)//restart grass rendering
  249. {
  250. mNumBlades = GRASS_MAX_BLADES ;
  251. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  252. return TRUE ;
  253. }
  254. if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime()))
  255. {
  256. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
  257. }
  258. return TRUE;
  259. }
  260. void LLVOGrass::setPixelAreaAndAngle(LLAgent &agent)
  261. {
  262. // This should be the camera's center, as soon as we move to all region-local.
  263. LLVector3 relative_position = getPositionAgent() - gAgentCamera.getCameraPositionAgent();
  264. F32 range = relative_position.length();
  265. F32 max_scale = getMaxScale();
  266. mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
  267. // Compute pixels per meter at the given range
  268. F32 pixels_per_meter = LLViewerCamera::getInstance()->getViewHeightInPixels() / (tan(LLViewerCamera::getInstance()->getView()) * range);
  269. // Assume grass texture is a 5 meter by 5 meter sprite at the grass object's center
  270. mPixelArea = (pixels_per_meter) * (pixels_per_meter) * 25.f;
  271. }
  272. // BUG could speed this up by caching the relative_position and range calculations
  273. void LLVOGrass::updateTextures()
  274. {
  275. if (getTEImage(0))
  276. {
  277. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
  278. {
  279. setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea)));
  280. }
  281. getTEImage(0)->addTextureStats(mPixelArea);
  282. }
  283. }
  284. BOOL LLVOGrass::updateLOD()
  285. {
  286. if (mDrawable->getNumFaces() <= 0)
  287. {
  288. return FALSE;
  289. }
  290. if(LLVOTree::isTreeRenderingStopped())
  291. {
  292. if(mNumBlades)
  293. {
  294. mNumBlades = 0 ;
  295. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  296. }
  297. return TRUE ;
  298. }
  299. if(!mNumBlades)
  300. {
  301. mNumBlades = GRASS_MAX_BLADES;
  302. }
  303. LLFace* face = mDrawable->getFace(0);
  304. F32 tan_angle = 0.f;
  305. S32 num_blades = 0;
  306. tan_angle = (mScale.mV[0]*mScale.mV[1])/mDrawable->mDistanceWRTCamera;
  307. num_blades = llmin(GRASS_MAX_BLADES, lltrunc(tan_angle * 5));
  308. num_blades = llmax(1, num_blades);
  309. if (num_blades >= (mNumBlades << 1))
  310. {
  311. while (mNumBlades < num_blades)
  312. {
  313. mNumBlades <<= 1;
  314. }
  315. face->setSize(mNumBlades*8, mNumBlades*12);
  316. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  317. }
  318. else if (num_blades <= (mNumBlades >> 1))
  319. {
  320. while (mNumBlades > num_blades)
  321. {
  322. mNumBlades >>=1;
  323. }
  324. face->setSize(mNumBlades*8, mNumBlades*12);
  325. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  326. return TRUE;
  327. }
  328. return FALSE;
  329. }
  330. LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline)
  331. {
  332. pipeline->allocDrawable(this);
  333. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GRASS);
  334. return mDrawable;
  335. }
  336. static LLFastTimer::DeclareTimer FTM_UPDATE_GRASS("Update Grass");
  337. BOOL LLVOGrass::updateGeometry(LLDrawable *drawable)
  338. {
  339. LLFastTimer ftm(FTM_UPDATE_GRASS);
  340. dirtySpatialGroup();
  341. if(!mNumBlades)//stop rendering grass
  342. {
  343. if (mDrawable->getNumFaces() > 0)
  344. {
  345. LLFace* facep = mDrawable->getFace(0);
  346. if(facep)
  347. {
  348. facep->setSize(0, 0);
  349. }
  350. }
  351. }
  352. else
  353. {
  354. plantBlades();
  355. }
  356. return TRUE;
  357. }
  358. void LLVOGrass::plantBlades()
  359. {
  360. // It is possible that the species of a grass is not defined
  361. // This is bad, but not the end of the world.
  362. if (!sSpeciesTable.count(mSpecies))
  363. {
  364. llinfos << "Unknown grass species " << mSpecies << llendl;
  365. return;
  366. }
  367. if (mDrawable->getNumFaces() < 1)
  368. {
  369. mDrawable->setNumFaces(1, NULL, getTEImage(0));
  370. }
  371. LLFace *face = mDrawable->getFace(0);
  372. face->setTexture(getTEImage(0));
  373. face->setState(LLFace::GLOBAL);
  374. face->setSize(mNumBlades * 8, mNumBlades * 12);
  375. face->setVertexBuffer(NULL);
  376. face->setTEOffset(0);
  377. face->mCenterLocal = mPosition + mRegionp->getOriginAgent();
  378. mDepth = (face->mCenterLocal - LLViewerCamera::getInstance()->getOrigin())*LLViewerCamera::getInstance()->getAtAxis();
  379. mDrawable->setPosition(face->mCenterLocal);
  380. mDrawable->movePartition();
  381. LLPipeline::sCompiles++;
  382. }
  383. void LLVOGrass::getGeometry(S32 idx,
  384. LLStrider<LLVector4a>& verticesp,
  385. LLStrider<LLVector3>& normalsp,
  386. LLStrider<LLVector2>& texcoordsp,
  387. LLStrider<LLColor4U>& colorsp,
  388. LLStrider<U16>& indicesp)
  389. {
  390. if(!mNumBlades)//stop rendering grass
  391. {
  392. return ;
  393. }
  394. mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
  395. if (mPatch)
  396. mLastPatchUpdateTime = mPatch->getLastUpdateTime();
  397. LLVector3 position;
  398. // Create random blades of grass with gaussian distribution
  399. F32 x,y,xf,yf,dzx,dzy;
  400. LLColor4U color(255,255,255,255);
  401. LLFace *face = mDrawable->getFace(idx);
  402. F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
  403. F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
  404. U32 index_offset = face->getGeomIndex();
  405. for (S32 i = 0; i < mNumBlades; i++)
  406. {
  407. x = exp_x[i] * mScale.mV[VX];
  408. y = exp_y[i] * mScale.mV[VY];
  409. xf = rot_x[i] * GRASS_BLADE_BASE * width * w_mod[i];
  410. yf = rot_y[i] * GRASS_BLADE_BASE * width * w_mod[i];
  411. dzx = dz_x [i];
  412. dzy = dz_y [i];
  413. LLVector3 v1,v2,v3;
  414. F32 blade_height= GRASS_BLADE_HEIGHT * height * w_mod[i];
  415. *texcoordsp++ = LLVector2(0, 0);
  416. *texcoordsp++ = LLVector2(0, 0);
  417. *texcoordsp++ = LLVector2(0, 0.98f);
  418. *texcoordsp++ = LLVector2(0, 0.98f);
  419. *texcoordsp++ = LLVector2(1, 0);
  420. *texcoordsp++ = LLVector2(1, 0);
  421. *texcoordsp++ = LLVector2(1, 0.98f);
  422. *texcoordsp++ = LLVector2(1, 0.98f);
  423. position.mV[0] = mPosition.mV[VX] + x + xf;
  424. position.mV[1] = mPosition.mV[VY] + y + yf;
  425. position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
  426. v1 = position + mRegionp->getOriginAgent();
  427. (*verticesp++).load3(v1.mV);
  428. (*verticesp++).load3(v1.mV);
  429. position.mV[0] += dzx;
  430. position.mV[1] += dzy;
  431. position.mV[2] += blade_height;
  432. v2 = position + mRegionp->getOriginAgent();
  433. (*verticesp++).load3(v2.mV);
  434. (*verticesp++).load3(v2.mV);
  435. position.mV[0] = mPosition.mV[VX] + x - xf;
  436. position.mV[1] = mPosition.mV[VY] + y - xf;
  437. position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
  438. v3 = position + mRegionp->getOriginAgent();
  439. (*verticesp++).load3(v3.mV);
  440. (*verticesp++).load3(v3.mV);
  441. LLVector3 normal1 = (v1-v2) % (v2-v3);
  442. normal1.mV[VZ] = 0.75f;
  443. normal1.normalize();
  444. LLVector3 normal2 = -normal1;
  445. normal2.mV[VZ] = -normal2.mV[VZ];
  446. position.mV[0] += dzx;
  447. position.mV[1] += dzy;
  448. position.mV[2] += blade_height;
  449. v1 = position + mRegionp->getOriginAgent();
  450. (*verticesp++).load3(v1.mV);
  451. (*verticesp++).load3(v1.mV);
  452. *(normalsp++) = normal1;
  453. *(normalsp++) = normal2;
  454. *(normalsp++) = normal1;
  455. *(normalsp++) = normal2;
  456. *(normalsp++) = normal1;
  457. *(normalsp++) = normal2;
  458. *(normalsp++) = normal1;
  459. *(normalsp++) = normal2;
  460. *(colorsp++) = color;
  461. *(colorsp++) = color;
  462. *(colorsp++) = color;
  463. *(colorsp++) = color;
  464. *(colorsp++) = color;
  465. *(colorsp++) = color;
  466. *(colorsp++) = color;
  467. *(colorsp++) = color;
  468. *indicesp++ = index_offset + 0;
  469. *indicesp++ = index_offset + 2;
  470. *indicesp++ = index_offset + 4;
  471. *indicesp++ = index_offset + 2;
  472. *indicesp++ = index_offset + 6;
  473. *indicesp++ = index_offset + 4;
  474. *indicesp++ = index_offset + 1;
  475. *indicesp++ = index_offset + 5;
  476. *indicesp++ = index_offset + 3;
  477. *indicesp++ = index_offset + 3;
  478. *indicesp++ = index_offset + 5;
  479. *indicesp++ = index_offset + 7;
  480. index_offset += 8;
  481. }
  482. LLPipeline::sCompiles++;
  483. }
  484. U32 LLVOGrass::getPartitionType() const
  485. {
  486. return LLViewerRegion::PARTITION_GRASS;
  487. }
  488. LLGrassPartition::LLGrassPartition()
  489. {
  490. mDrawableType = LLPipeline::RENDER_TYPE_GRASS;
  491. mPartitionType = LLViewerRegion::PARTITION_GRASS;
  492. mLODPeriod = 16;
  493. mDepthMask = TRUE;
  494. mSlopRatio = 0.1f;
  495. mRenderPass = LLRenderPass::PASS_GRASS;
  496. mBufferUsage = GL_DYNAMIC_DRAW_ARB;
  497. }
  498. // virtual
  499. void LLVOGrass::updateDrawable(BOOL force_damped)
  500. {
  501. // Force an immediate rebuild on any update
  502. if (mDrawable.notNull())
  503. {
  504. mDrawable->updateXform(TRUE);
  505. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
  506. }
  507. clearChanged(SHIFTED);
  508. }
  509. // virtual
  510. BOOL LLVOGrass::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp,
  511. LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
  512. {
  513. BOOL ret = FALSE;
  514. if (!mbCanSelect ||
  515. mDrawable->isDead() ||
  516. !gPipeline.hasRenderType(mDrawable->getRenderType()))
  517. {
  518. return FALSE;
  519. }
  520. LLVector3 dir = end-start;
  521. mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion());
  522. LLVector3 position;
  523. // Create random blades of grass with gaussian distribution
  524. F32 x,y,xf,yf,dzx,dzy;
  525. LLColor4U color(255,255,255,255);
  526. F32 width = sSpeciesTable[mSpecies]->mBladeSizeX;
  527. F32 height = sSpeciesTable[mSpecies]->mBladeSizeY;
  528. LLVector2 tc[4];
  529. LLVector3 v[4];
  530. //LLVector3 n[4];
  531. F32 closest_t = 1.f;
  532. for (S32 i = 0; i < mNumBlades; i++)
  533. {
  534. x = exp_x[i] * mScale.mV[VX];
  535. y = exp_y[i] * mScale.mV[VY];
  536. xf = rot_x[i] * GRASS_BLADE_BASE * width * w_mod[i];
  537. yf = rot_y[i] * GRASS_BLADE_BASE * width * w_mod[i];
  538. dzx = dz_x [i];
  539. dzy = dz_y [i];
  540. LLVector3 v1,v2,v3;
  541. F32 blade_height= GRASS_BLADE_HEIGHT * height * w_mod[i];
  542. tc[0] = LLVector2(0, 0);
  543. tc[1] = LLVector2(0, 0.98f);
  544. tc[2] = LLVector2(1, 0);
  545. tc[3] = LLVector2(1, 0.98f);
  546. position.mV[0] = mPosition.mV[VX] + x + xf;
  547. position.mV[1] = mPosition.mV[VY] + y + yf;
  548. position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
  549. v[0] = v1 = position + mRegionp->getOriginAgent();
  550. position.mV[0] += dzx;
  551. position.mV[1] += dzy;
  552. position.mV[2] += blade_height;
  553. v[1] = v2 = position + mRegionp->getOriginAgent();
  554. position.mV[0] = mPosition.mV[VX] + x - xf;
  555. position.mV[1] = mPosition.mV[VY] + y - xf;
  556. position.mV[2] = mRegionp->getLand().resolveHeightRegion(position);
  557. v[2] = v3 = position + mRegionp->getOriginAgent();
  558. LLVector3 normal1 = (v1-v2) % (v2-v3);
  559. normal1.normalize();
  560. position.mV[0] += dzx;
  561. position.mV[1] += dzy;
  562. position.mV[2] += blade_height;
  563. v[3] = v1 = position + mRegionp->getOriginAgent();
  564. F32 a,b,t;
  565. BOOL hit = FALSE;
  566. U32 idx0 = 0,idx1 = 0,idx2 = 0;
  567. if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE))
  568. {
  569. hit = TRUE;
  570. idx0 = 0; idx1 = 1; idx2 = 2;
  571. }
  572. else if (LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, a, b, t, FALSE))
  573. {
  574. hit = TRUE;
  575. idx0 = 1; idx1 = 3; idx2 = 2;
  576. }
  577. else if (LLTriangleRayIntersect(v[2], v[1], v[0], start, dir, a, b, t, FALSE))
  578. {
  579. normal1 = -normal1;
  580. hit = TRUE;
  581. idx0 = 2; idx1 = 1; idx2 = 0;
  582. }
  583. else if (LLTriangleRayIntersect(v[2], v[3], v[1], start, dir, a, b, t, FALSE))
  584. {
  585. normal1 = -normal1;
  586. hit = TRUE;
  587. idx0 = 2; idx1 = 3; idx2 = 1;
  588. }
  589. if (hit)
  590. {
  591. if (t >= 0.f &&
  592. t <= 1.f &&
  593. t < closest_t)
  594. {
  595. LLVector2 hit_tc = ((1.f - a - b) * tc[idx0] +
  596. a * tc[idx1] +
  597. b * tc[idx2]);
  598. if (pick_transparent ||
  599. getTEImage(0)->getMask(hit_tc))
  600. {
  601. closest_t = t;
  602. if (intersection != NULL)
  603. {
  604. *intersection = start+dir*closest_t;
  605. }
  606. if (tex_coord != NULL)
  607. {
  608. *tex_coord = hit_tc;
  609. }
  610. if (normal != NULL)
  611. {
  612. *normal = normal1;
  613. }
  614. ret = TRUE;
  615. }
  616. }
  617. }
  618. }
  619. return ret;
  620. }