streak.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : G *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/segline.cpp $*
  25. * *
  26. * $Author:: Vss_sync $*
  27. * *
  28. * $Modtime:: 8/29/01 7:29p $*
  29. * *
  30. * $Revision:: 23 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "streak.h"
  36. #include "ww3d.h"
  37. #include "rinfo.h"
  38. #include "predlod.h"
  39. #include "v3_rnd.h"
  40. #include "texture.h"
  41. #include "coltest.h"
  42. #include "w3d_file.h"
  43. #include "texture.h"
  44. #include "dx8wrapper.h"
  45. #include "vp.h"
  46. #include "vector3i.h"
  47. #include "sortingrenderer.h"
  48. static SegLineRendererClass _LineRenderer;
  49. /*
  50. ** StreakLineClass implementation:
  51. */
  52. StreakLineClass::StreakLineClass(void) :
  53. MaxSubdivisionLevels(0),
  54. NormalizedScreenArea(0.0f)
  55. {
  56. Personalities = NULL;
  57. }
  58. StreakLineClass::StreakLineClass(const StreakLineClass & src) :
  59. MaxSubdivisionLevels(src.MaxSubdivisionLevels),
  60. NormalizedScreenArea(src.NormalizedScreenArea),
  61. PointLocations(src.PointLocations),
  62. PointColors(src.PointColors),
  63. PointWidths(src.PointWidths),
  64. LineRenderer(src.LineRenderer),
  65. StreakRenderer(src.StreakRenderer),
  66. Personalities(src.Personalities)
  67. {
  68. }
  69. StreakLineClass & StreakLineClass::operator = (const StreakLineClass &that)
  70. {
  71. RenderObjClass::operator = (that);
  72. if (this != &that) {
  73. MaxSubdivisionLevels = that.MaxSubdivisionLevels;
  74. NormalizedScreenArea = that.NormalizedScreenArea;
  75. PointLocations = that.PointLocations;
  76. PointColors = that.PointColors;
  77. PointWidths = that.PointWidths;
  78. LineRenderer = that.LineRenderer;
  79. StreakRenderer = that.StreakRenderer;
  80. Personalities = that.Personalities;
  81. }
  82. return * this;
  83. }
  84. //StreakLineClass::~StreakLineClass(void)
  85. //{
  86. //}
  87. void StreakLineClass::Reset_Line(void)
  88. {
  89. LineRenderer.Reset_Line();
  90. StreakRenderer.Reset_Line();
  91. }
  92. ////////////////////////////////////////////////////////////////////////////
  93. ////////////////////////////////////////////////////////////////////////////
  94. ////////////////////////////////////////////////////////////////////////////
  95. // These are segment points, and include the start and end point of the
  96. // entire line. Therefore there must be at least two.
  97. void StreakLineClass::Set_Locs( unsigned int num_points, Vector3 *locs )
  98. {
  99. if (num_points < 2 || !locs) {
  100. WWASSERT(0);
  101. return;
  102. }
  103. PointLocations.Delete_All();
  104. for (unsigned int i=0; i<num_points; i++) {
  105. PointLocations.Add(locs[i],num_points);
  106. }
  107. Invalidate_Cached_Bounding_Volumes();
  108. }
  109. void StreakLineClass::Set_Widths( unsigned int num_points, float *widths )
  110. {
  111. if (num_points < 2 || !widths) {
  112. WWASSERT(0);
  113. return;
  114. }
  115. PointWidths.Delete_All();
  116. for (unsigned int i=0; i<num_points; i++) {
  117. PointWidths.Add(widths[i],num_points);
  118. }
  119. }
  120. void StreakLineClass::Set_Colors( unsigned int num_points, Vector4 *colors )
  121. {
  122. if (num_points < 2 || !colors) {
  123. WWASSERT(0);
  124. return;
  125. }
  126. PointColors.Delete_All();
  127. for (unsigned int i=0; i<num_points; i++) {
  128. PointColors.Add(colors[i],num_points);
  129. }
  130. }
  131. void StreakLineClass::Set_LocsWidthsColors( unsigned int num_points,
  132. Vector3 *locs,
  133. float *widths,
  134. Vector4 *colors,
  135. unsigned int *personalities)
  136. {
  137. Personalities = personalities;
  138. Set_Locs( num_points, locs );
  139. if (widths)
  140. {
  141. Set_Widths( num_points, widths );
  142. //sanity check
  143. int locCount = PointLocations.Count();
  144. int widCount = PointWidths.Count();
  145. WWASSERT(locCount == widCount);
  146. }
  147. if (colors)
  148. {
  149. Set_Colors( num_points, colors );
  150. //sanity check
  151. int locCount = PointLocations.Count();
  152. int colCount = PointColors.Count();
  153. WWASSERT(locCount == colCount);
  154. }
  155. Invalidate_Cached_Bounding_Volumes();
  156. }
  157. ////////////////////////////////////////////////////////////////////////////
  158. ////////////////////////////////////////////////////////////////////////////
  159. ////////////////////////////////////////////////////////////////////////////
  160. // These are segment points, and include the start and end point of the
  161. // entire line. Therefore there must be at least two.
  162. int StreakLineClass::Get_Num_Points(void)
  163. {
  164. int locCount = PointLocations.Count();
  165. return locCount;
  166. }
  167. // Set object-space location for a given point.
  168. // NOTE: If given position beyond end of point list, do nothing.
  169. void StreakLineClass::Set_Point_Location(unsigned int point_idx, const Vector3 &location)
  170. {
  171. if (point_idx < (unsigned int)PointLocations.Count()) {
  172. PointLocations[point_idx] = location;
  173. }
  174. Invalidate_Cached_Bounding_Volumes();
  175. }
  176. // Get object-space location of a given point (if position beyond end of
  177. // point list, will return 0,0,0).
  178. void StreakLineClass::Get_Point_Location(unsigned int point_idx, Vector3 &loc)
  179. {
  180. if (point_idx < (unsigned int)PointLocations.Count()) {
  181. loc.Set(PointLocations[point_idx]);
  182. } else {
  183. loc.Set(0, 0, 0);
  184. }
  185. }
  186. void StreakLineClass::Add_Point(const Vector3 & location)
  187. {
  188. PointLocations.Add(location);
  189. }
  190. void StreakLineClass::Delete_Point(unsigned int point_idx)
  191. {
  192. if (point_idx < (unsigned int)PointLocations.Count()) {
  193. PointLocations.Delete(point_idx);
  194. }
  195. }
  196. TextureClass * StreakLineClass::Get_Texture(void)
  197. {
  198. return LineRenderer.Get_Texture();
  199. }
  200. ShaderClass StreakLineClass::Get_Shader(void)
  201. {
  202. return LineRenderer.Get_Shader();
  203. }
  204. void StreakLineClass::Get_Color(Vector3 &color)
  205. {
  206. color.Set(LineRenderer.Get_Color());
  207. }
  208. float StreakLineClass::Get_Opacity(void)
  209. {
  210. return LineRenderer.Get_Opacity();
  211. }
  212. float StreakLineClass::Get_Noise_Amplitude(void)
  213. {
  214. return LineRenderer.Get_Noise_Amplitude();
  215. }
  216. float StreakLineClass::Get_Merge_Abort_Factor(void)
  217. {
  218. return LineRenderer.Get_Merge_Abort_Factor();
  219. }
  220. unsigned int StreakLineClass::Get_Subdivision_Levels(void)
  221. {
  222. return MaxSubdivisionLevels;
  223. }
  224. SegLineRendererClass::TextureMapMode StreakLineClass::Get_Texture_Mapping_Mode(void)
  225. {
  226. return LineRenderer.Get_Texture_Mapping_Mode();
  227. }
  228. float StreakLineClass::Get_Texture_Tile_Factor(void)
  229. {
  230. return LineRenderer.Get_Texture_Tile_Factor();
  231. }
  232. Vector2 StreakLineClass::Get_UV_Offset_Rate(void)
  233. {
  234. return LineRenderer.Get_UV_Offset_Rate();
  235. }
  236. int StreakLineClass::Is_Merge_Intersections(void)
  237. {
  238. return LineRenderer.Is_Merge_Intersections();
  239. }
  240. int StreakLineClass::Is_Freeze_Random(void)
  241. {
  242. return LineRenderer.Is_Freeze_Random();
  243. }
  244. int StreakLineClass::Is_Sorting_Disabled(void)
  245. {
  246. return LineRenderer.Is_Sorting_Disabled();
  247. }
  248. int StreakLineClass::Are_End_Caps_Enabled(void)
  249. {
  250. return LineRenderer.Are_End_Caps_Enabled();
  251. }
  252. void StreakLineClass::Set_Texture(TextureClass *texture)
  253. {
  254. LineRenderer.Set_Texture(texture);
  255. StreakRenderer.Set_Texture(texture);
  256. }
  257. void StreakLineClass::Set_Shader(ShaderClass shader)
  258. {
  259. LineRenderer.Set_Shader(shader);
  260. StreakRenderer.Set_Shader(shader);
  261. }
  262. float StreakLineClass::Get_Width(void)
  263. {
  264. return LineRenderer.Get_Width();
  265. }
  266. void StreakLineClass::Set_Width(float width)
  267. {
  268. // Widths need to be clamped because they are not automatically clamped later (like colors and
  269. // alphas are).
  270. LineRenderer.Set_Width(MAX(width, 0.0f));
  271. StreakRenderer.Set_Width(MAX(width, 0.0f));
  272. Invalidate_Cached_Bounding_Volumes();
  273. }
  274. void StreakLineClass::Set_Color(const Vector3 &color)
  275. {
  276. LineRenderer.Set_Color(color);
  277. StreakRenderer.Set_Color(color);
  278. }
  279. void StreakLineClass::Set_Opacity(float opacity)
  280. {
  281. LineRenderer.Set_Opacity(opacity);
  282. StreakRenderer.Set_Opacity(opacity);
  283. }
  284. void StreakLineClass::Set_Noise_Amplitude(float amplitude)
  285. {
  286. LineRenderer.Set_Noise_Amplitude(WWMath::Fabs(amplitude));
  287. Invalidate_Cached_Bounding_Volumes();
  288. }
  289. void StreakLineClass::Set_Merge_Abort_Factor(float factor)
  290. {
  291. LineRenderer.Set_Merge_Abort_Factor(factor);
  292. }
  293. void StreakLineClass::Set_Subdivision_Levels(unsigned int levels)
  294. {
  295. MaxSubdivisionLevels = MIN(levels, MAX_SEGLINE_SUBDIV_LEVELS);
  296. Invalidate_Cached_Bounding_Volumes();
  297. }
  298. void StreakLineClass::Set_Texture_Mapping_Mode(SegLineRendererClass::TextureMapMode mode)
  299. {
  300. LineRenderer.Set_Texture_Mapping_Mode(mode);
  301. }
  302. void StreakLineClass::Set_Texture_Tile_Factor(float factor)
  303. {
  304. LineRenderer.Set_Texture_Tile_Factor(factor);
  305. }
  306. void StreakLineClass::Set_UV_Offset_Rate(const Vector2 &rate)
  307. {
  308. LineRenderer.Set_UV_Offset_Rate(rate);
  309. }
  310. void StreakLineClass::Set_Merge_Intersections(int onoff)
  311. {
  312. LineRenderer.Set_Merge_Intersections(onoff);
  313. }
  314. void StreakLineClass::Set_Freeze_Random(int onoff)
  315. {
  316. LineRenderer.Set_Freeze_Random(onoff);
  317. }
  318. void StreakLineClass::Set_Disable_Sorting(int onoff)
  319. {
  320. LineRenderer.Set_Disable_Sorting(onoff);
  321. }
  322. void StreakLineClass::Set_End_Caps(int onoff)
  323. {
  324. LineRenderer.Set_End_Caps(onoff);
  325. }
  326. /*
  327. ** RenderObjClass interface:
  328. */
  329. RenderObjClass * StreakLineClass::Clone(void) const
  330. {
  331. return NEW_REF( StreakLineClass, (*this));
  332. }
  333. int StreakLineClass::Get_Num_Polys(void) const
  334. {
  335. int subdivision_factor = 1 << LineRenderer.Get_Current_Subdivision_Level();
  336. return 2 * (PointLocations.Count() - 1) * subdivision_factor;
  337. }
  338. void StreakLineClass::Render(RenderInfoClass & rinfo)
  339. {
  340. if (Is_Not_Hidden_At_All() == false) {
  341. return ;
  342. }
  343. // Process texture reductions:
  344. // if (LineRenderer.Peek_Texture()) LineRenderer.Peek_Texture()->Process_Reduction();
  345. unsigned int sort_level = SORT_LEVEL_NONE;
  346. if (!WW3D::Is_Sorting_Enabled())
  347. sort_level=Get_Shader().Guess_Sort_Level();
  348. if (WW3D::Are_Static_Sort_Lists_Enabled() && sort_level!=SORT_LEVEL_NONE) {
  349. WW3D::Add_To_Static_Sort_List(this, sort_level);
  350. }
  351. else
  352. {
  353. if ( !PointColors.Count() || !PointWidths.Count() )
  354. {
  355. Render_Seg_Line(rinfo);
  356. }
  357. else
  358. {
  359. Render_Streak_Line(rinfo);
  360. }
  361. }
  362. }
  363. void StreakLineClass::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  364. {
  365. // Get object-space bounding box and create bounding sphere from it
  366. AABoxClass box;
  367. Get_Obj_Space_Bounding_Box(box);
  368. // Create object-space bounding sphere from the bounding box:
  369. sphere.Center = box.Center;
  370. sphere.Radius = box.Extent.Length();
  371. }
  372. void StreakLineClass::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  373. {
  374. unsigned int num_points = PointLocations.Count();
  375. // Line must have at least two points to be valid
  376. if (num_points >= 2) {
  377. // Find object-space axis-aligned bounding box
  378. Vector3 max_coords;
  379. Vector3 min_coords;
  380. unsigned int i;
  381. // We create two bounding boxes; one from the points, and if we have random noise
  382. // subdivision we create another one from the midpoints and factor the noise amplitude
  383. // into the second box, and then combine the two.
  384. // First bounding box:
  385. max_coords = PointLocations[0];
  386. min_coords = PointLocations[0];
  387. for (i = 1; i < num_points; i++) {
  388. max_coords.Update_Max(PointLocations[i]);
  389. min_coords.Update_Min(PointLocations[i]);
  390. }
  391. // Enlarge bounding box by half the width
  392. float enlarge_factor = LineRenderer.Get_Width() * 0.5f;
  393. Vector3 enlarge_offset;
  394. enlarge_offset.Set(enlarge_factor, enlarge_factor, enlarge_factor);
  395. max_coords += enlarge_offset;
  396. min_coords -= enlarge_offset;
  397. if (MaxSubdivisionLevels > 0) {
  398. // Second bounding box:
  399. Vector3 max_coords2;
  400. Vector3 min_coords2;
  401. Vector3 midpoint = (PointLocations[0] + PointLocations[1]) * 0.5f;
  402. max_coords2 = midpoint;
  403. min_coords2 = midpoint;
  404. for (i = 1; i < num_points - 1; i++) {
  405. midpoint = (PointLocations[i] + PointLocations[i + 1]) * 0.5f;
  406. max_coords2.Update_Max(midpoint);
  407. min_coords2.Update_Min(midpoint);
  408. }
  409. // We ignore the actual number of subdivision levels: we multiply the random noise
  410. // amplitude by 2, which is the limit as the number of subdivision levels goes to
  411. // infinity.
  412. enlarge_factor += (2 * LineRenderer.Get_Noise_Amplitude());
  413. enlarge_offset.Set(enlarge_factor, enlarge_factor, enlarge_factor);
  414. max_coords2 += enlarge_offset;
  415. min_coords2 -= enlarge_offset;
  416. // Combine the two:
  417. max_coords.Update_Max(max_coords2);
  418. min_coords.Update_Min(min_coords2);
  419. }
  420. box.Init_Min_Max(min_coords, max_coords);
  421. } else {
  422. // Invalid line - return something
  423. box.Init(Vector3(0,0,0),Vector3(1,1,1));
  424. }
  425. }
  426. void StreakLineClass::Prepare_LOD(CameraClass &camera)
  427. {
  428. // Find the maximum screen dimension of the object in pixels
  429. NormalizedScreenArea = Get_Screen_Size(camera);
  430. // // Find and set texture reduction factor
  431. // Set_Texture_Reduction_Factor(Calculate_Texture_Reduction_Factor(NormalizedScreenArea));
  432. // Ensure subdivision level is legal
  433. unsigned int lvl = LineRenderer.Get_Current_Subdivision_Level();
  434. lvl = MIN(lvl, MaxSubdivisionLevels);
  435. LineRenderer.Set_Current_Subdivision_Level(lvl);
  436. // Prepare LOD processing if the line has subdivision enabled:
  437. if (MaxSubdivisionLevels > 0) {
  438. // Add myself to the LOD optimizer:
  439. PredictiveLODOptimizerClass::Add_Object(this);
  440. } else {
  441. // Not added to optimizer, need to add cost
  442. PredictiveLODOptimizerClass::Add_Cost(Get_Cost());
  443. }
  444. }
  445. void StreakLineClass::Increment_LOD(void)
  446. {
  447. unsigned int lvl = LineRenderer.Get_Current_Subdivision_Level();
  448. lvl = MIN(lvl+1,MaxSubdivisionLevels);
  449. LineRenderer.Set_Current_Subdivision_Level(lvl);
  450. }
  451. void StreakLineClass::Decrement_LOD(void)
  452. {
  453. int lvl = LineRenderer.Get_Current_Subdivision_Level();
  454. if (lvl == 0) return;
  455. LineRenderer.Set_Current_Subdivision_Level(lvl-1);
  456. }
  457. float StreakLineClass::Get_Cost(void) const
  458. {
  459. return Get_Num_Polys();
  460. }
  461. float StreakLineClass::Get_Value(void) const
  462. {
  463. // If we are at the minimum LOD, we must return AT_MIN_LOD.
  464. if (LineRenderer.Get_Current_Subdivision_Level() == 0) {
  465. return AT_MIN_LOD;
  466. } else {
  467. float polycount = (float)Get_Num_Polys();
  468. float benefit_factor = 1.0f - (0.5f / (polycount * polycount));
  469. return (benefit_factor * NormalizedScreenArea) / Get_Cost();
  470. }
  471. }
  472. float StreakLineClass::Get_Post_Increment_Value(void) const
  473. {
  474. // If we are at the maximum LOD, we must return AT_MIN_LOD.
  475. if (LineRenderer.Get_Current_Subdivision_Level() == MaxSubdivisionLevels) {
  476. return AT_MAX_LOD;
  477. } else {
  478. // Assumption: each subdivision level doubles polycount
  479. float polycount = 2.0f * (float)Get_Num_Polys();
  480. float benefit_factor = 1.0f - (0.5f / (polycount * polycount));
  481. // Assumption: Cost() == polycount
  482. return (benefit_factor * NormalizedScreenArea) / polycount;
  483. }
  484. }
  485. void StreakLineClass::Set_LOD_Level(int lod)
  486. {
  487. lod = MAX(0, lod);
  488. lod = MIN(lod, (int)MaxSubdivisionLevels);
  489. LineRenderer.Set_Current_Subdivision_Level((unsigned int)lod);
  490. }
  491. int StreakLineClass::Get_LOD_Level(void) const
  492. {
  493. return (int) LineRenderer.Get_Current_Subdivision_Level();
  494. }
  495. int StreakLineClass::Get_LOD_Count(void) const
  496. {
  497. return (int)MaxSubdivisionLevels;
  498. }
  499. /*
  500. void StreakLineClass::Set_Texture_Reduction_Factor(float trf)
  501. {
  502. if (LineRenderer.Peek_Texture()) LineRenderer.Peek_Texture()->Set_Reduction_Factor(trf);
  503. }*/
  504. void StreakLineClass::Render_Seg_Line(RenderInfoClass & rinfo)
  505. {
  506. // Line must have at least two points to be valid
  507. if (PointLocations.Count() < 2) return;
  508. SphereClass bounding_sphere;
  509. Get_Obj_Space_Bounding_Sphere(bounding_sphere);
  510. // LineRenderer.Set_Width(rand()%3);
  511. LineRenderer.Render(
  512. rinfo,
  513. Transform,
  514. PointLocations.Count(),
  515. &(PointLocations[0]),
  516. bounding_sphere
  517. );
  518. }
  519. void StreakLineClass::Render_Streak_Line(RenderInfoClass & rinfo)
  520. {
  521. WWASSERT(PointLocations.Count() == PointColors.Count());
  522. WWASSERT(PointLocations.Count() == PointWidths.Count());
  523. // Line must have at least two points to be valid
  524. if (PointLocations.Count() < 2) return;
  525. if (PointColors.Count() < 2) return;
  526. if (PointWidths.Count() < 2) return;
  527. if(PointLocations.Count() != PointColors.Count()) return;
  528. if(PointLocations.Count() != PointWidths.Count()) return;
  529. SphereClass bounding_sphere;
  530. Get_Obj_Space_Bounding_Sphere(bounding_sphere);
  531. // StreakRenderer.Render(
  532. // rinfo,
  533. // Transform,
  534. // PointLocations.Count(),
  535. // &(PointLocations[0]),
  536. // bounding_sphere
  537. // );
  538. StreakRenderer.RenderStreak(
  539. rinfo,
  540. Transform,
  541. PointLocations.Count(),
  542. &(PointLocations[0]),
  543. &(PointColors[0]),
  544. &(PointWidths[0]),
  545. bounding_sphere,
  546. Personalities
  547. );
  548. }
  549. bool StreakLineClass::Cast_Ray(RayCollisionTestClass & raytest)
  550. {
  551. if ((Get_Collision_Type() & raytest.CollisionType) == 0) return false;
  552. bool retval = false;
  553. //
  554. // Check each line segment against the ray
  555. //
  556. float fraction = 1.0F;
  557. for (uint32 index = 1; index < (unsigned int)PointLocations.Count(); index ++)
  558. {
  559. #ifdef ALLOW_TEMPORARIES
  560. Vector3 curr_start = Transform * PointLocations[index-1];
  561. Vector3 curr_end = Transform * PointLocations[index];
  562. LineSegClass line_seg (curr_start, curr_end);
  563. #else
  564. Vector3 curr[2];
  565. Transform.mulVector3Array(&PointLocations[index-1], curr, 2);
  566. LineSegClass line_seg(curr[0], curr[1]);
  567. #endif
  568. Vector3 p0;
  569. Vector3 p1;
  570. if (raytest.Ray.Find_Intersection (line_seg, &p0, &fraction, &p1, NULL)) {
  571. //
  572. // Determine if the ray was close enough to this line to be
  573. // considered intersecting
  574. //
  575. float dist = (p0 - p1).Length ();
  576. if (dist <= LineRenderer.Get_Width() && fraction >= 0 && fraction < raytest.Result->Fraction) {
  577. //if (dist <= Width && fraction < raytest.Result->Fraction) {
  578. retval = true;
  579. break;
  580. }
  581. }
  582. }
  583. //
  584. // Fill in the raytest structure if we were successfull
  585. //
  586. if (retval) {
  587. raytest.Result->Fraction = fraction;
  588. raytest.Result->SurfaceType = SURFACE_TYPE_DEFAULT;
  589. raytest.CollidedRenderObj = this;
  590. }
  591. return retval;
  592. }