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

游戏引擎

开发平台:

C++ Builder

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