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

游戏引擎

开发平台:

C++ Builder

  1. {
  2. // we don't allow LLVolumes with this many vertices
  3. llwarns << "Couldn't allocate triangle indices" << llendl;
  4. num_indices = 0;
  5. return NULL;
  6. }
  7. S32* index = new S32[expected_num_triangle_indices];
  8. S32 count = 0;
  9. // Let's do this totally diffently, as we don't care about faces...
  10. // Counter-clockwise triangles are forward facing...
  11. BOOL open = getProfile().isOpen();
  12. BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
  13. BOOL path_open = getPath().isOpen();
  14. S32 size_s, size_s_out, size_t;
  15. S32 s, t, i;
  16. size_s = getProfile().getTotal();
  17. size_s_out = getProfile().getTotalOut();
  18. size_t = getPath().mPath.size();
  19. // NOTE -- if the construction of the triangles below ever changes
  20. // then getNumTriangleIndices() method may also have to be updated.
  21. if (open) /* Flawfinder: ignore */
  22. {
  23. if (hollow)
  24. {
  25. // Open hollow -- much like the closed solid, except we 
  26. // we need to stitch up the gap between s=0 and s=size_s-1
  27. for (t = 0; t < size_t - 1; t++)
  28. {
  29. // The outer face, first cut, and inner face
  30. for (s = 0; s < size_s - 1; s++)
  31. {
  32. i  = s + t*size_s;
  33. index[count++]  = i; // x,y
  34. index[count++]  = i + 1; // x+1,y
  35. index[count++]  = i + size_s; // x,y+1
  36. index[count++]  = i + size_s; // x,y+1
  37. index[count++]  = i + 1; // x+1,y
  38. index[count++]  = i + size_s + 1; // x+1,y+1
  39. }
  40. // The other cut face
  41. index[count++]  = s + t*size_s; // x,y
  42. index[count++]  = 0 + t*size_s; // x+1,y
  43. index[count++]  = s + (t+1)*size_s; // x,y+1
  44. index[count++]  = s + (t+1)*size_s; // x,y+1
  45. index[count++]  = 0 + t*size_s; // x+1,y
  46. index[count++]  = 0 + (t+1)*size_s; // x+1,y+1
  47. }
  48. // Do the top and bottom caps, if necessary
  49. if (path_open)
  50. {
  51. // Top cap
  52. S32 pt1 = 0;
  53. S32 pt2 = size_s-1;
  54. S32 i   = (size_t - 1)*size_s;
  55. while (pt2 - pt1 > 1)
  56. {
  57. // Use the profile points instead of the mesh, since you want
  58. // the un-transformed profile distances.
  59. LLVector3 p1 = getProfile().mProfile[pt1];
  60. LLVector3 p2 = getProfile().mProfile[pt2];
  61. LLVector3 pa = getProfile().mProfile[pt1+1];
  62. LLVector3 pb = getProfile().mProfile[pt2-1];
  63. p1.mV[VZ] = 0.f;
  64. p2.mV[VZ] = 0.f;
  65. pa.mV[VZ] = 0.f;
  66. pb.mV[VZ] = 0.f;
  67. // Use area of triangle to determine backfacing
  68. F32 area_1a2, area_1ba, area_21b, area_2ab;
  69. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  70. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  71. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  72. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  73. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  74. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  75. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  76. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  77. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  78. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  79. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  80. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  81. BOOL use_tri1a2 = TRUE;
  82. BOOL tri_1a2 = TRUE;
  83. BOOL tri_21b = TRUE;
  84. if (area_1a2 < 0)
  85. {
  86. tri_1a2 = FALSE;
  87. }
  88. if (area_2ab < 0)
  89. {
  90. // Can't use, because it contains point b
  91. tri_1a2 = FALSE;
  92. }
  93. if (area_21b < 0)
  94. {
  95. tri_21b = FALSE;
  96. }
  97. if (area_1ba < 0)
  98. {
  99. // Can't use, because it contains point b
  100. tri_21b = FALSE;
  101. }
  102. if (!tri_1a2)
  103. {
  104. use_tri1a2 = FALSE;
  105. }
  106. else if (!tri_21b)
  107. {
  108. use_tri1a2 = TRUE;
  109. }
  110. else
  111. {
  112. LLVector3 d1 = p1 - pa;
  113. LLVector3 d2 = p2 - pb;
  114. if (d1.magVecSquared() < d2.magVecSquared())
  115. {
  116. use_tri1a2 = TRUE;
  117. }
  118. else
  119. {
  120. use_tri1a2 = FALSE;
  121. }
  122. }
  123. if (use_tri1a2)
  124. {
  125. index[count++] = pt1 + i;
  126. index[count++] = pt1 + 1 + i;
  127. index[count++] = pt2 + i;
  128. pt1++;
  129. }
  130. else
  131. {
  132. index[count++] = pt1 + i;
  133. index[count++] = pt2 - 1 + i;
  134. index[count++] = pt2 + i;
  135. pt2--;
  136. }
  137. }
  138. // Bottom cap
  139. pt1          = 0;
  140. pt2          = size_s-1;
  141. while (pt2 - pt1 > 1)
  142. {
  143. // Use the profile points instead of the mesh, since you want
  144. // the un-transformed profile distances.
  145. LLVector3 p1 = getProfile().mProfile[pt1];
  146. LLVector3 p2 = getProfile().mProfile[pt2];
  147. LLVector3 pa = getProfile().mProfile[pt1+1];
  148. LLVector3 pb = getProfile().mProfile[pt2-1];
  149. p1.mV[VZ] = 0.f;
  150. p2.mV[VZ] = 0.f;
  151. pa.mV[VZ] = 0.f;
  152. pb.mV[VZ] = 0.f;
  153. // Use area of triangle to determine backfacing
  154. F32 area_1a2, area_1ba, area_21b, area_2ab;
  155. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  156. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  157. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  158. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  159. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  160. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  161. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  162. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  163. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  164. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  165. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  166. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  167. BOOL use_tri1a2 = TRUE;
  168. BOOL tri_1a2 = TRUE;
  169. BOOL tri_21b = TRUE;
  170. if (area_1a2 < 0)
  171. {
  172. tri_1a2 = FALSE;
  173. }
  174. if (area_2ab < 0)
  175. {
  176. // Can't use, because it contains point b
  177. tri_1a2 = FALSE;
  178. }
  179. if (area_21b < 0)
  180. {
  181. tri_21b = FALSE;
  182. }
  183. if (area_1ba < 0)
  184. {
  185. // Can't use, because it contains point b
  186. tri_21b = FALSE;
  187. }
  188. if (!tri_1a2)
  189. {
  190. use_tri1a2 = FALSE;
  191. }
  192. else if (!tri_21b)
  193. {
  194. use_tri1a2 = TRUE;
  195. }
  196. else
  197. {
  198. LLVector3 d1 = p1 - pa;
  199. LLVector3 d2 = p2 - pb;
  200. if (d1.magVecSquared() < d2.magVecSquared())
  201. {
  202. use_tri1a2 = TRUE;
  203. }
  204. else
  205. {
  206. use_tri1a2 = FALSE;
  207. }
  208. }
  209. if (use_tri1a2)
  210. {
  211. index[count++] = pt1;
  212. index[count++] = pt2;
  213. index[count++] = pt1 + 1;
  214. pt1++;
  215. }
  216. else
  217. {
  218. index[count++] = pt1;
  219. index[count++] = pt2;
  220. index[count++] = pt2 - 1;
  221. pt2--;
  222. }
  223. }
  224. }
  225. }
  226. else
  227. {
  228. // Open solid
  229. for (t = 0; t < size_t - 1; t++)
  230. {
  231. // Outer face + 1 cut face
  232. for (s = 0; s < size_s - 1; s++)
  233. {
  234. i  = s + t*size_s;
  235. index[count++]  = i; // x,y
  236. index[count++]  = i + 1; // x+1,y
  237. index[count++]  = i + size_s; // x,y+1
  238. index[count++]  = i + size_s; // x,y+1
  239. index[count++]  = i + 1; // x+1,y
  240. index[count++]  = i + size_s + 1; // x+1,y+1
  241. }
  242. // The other cut face
  243. index[count++] = (size_s - 1) + (t*size_s); // x,y
  244. index[count++] = 0 + t*size_s; // x+1,y
  245. index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1
  246. index[count++] = (size_s - 1) + (t+1)*size_s; // x,y+1
  247. index[count++] = 0 + (t*size_s); // x+1,y
  248. index[count++] = 0 + (t+1)*size_s; // x+1,y+1
  249. }
  250. // Do the top and bottom caps, if necessary
  251. if (path_open)
  252. {
  253. for (s = 0; s < size_s - 2; s++)
  254. {
  255. index[count++] = s+1;
  256. index[count++] = s;
  257. index[count++] = size_s - 1;
  258. }
  259. // We've got a top cap
  260. S32 offset = (size_t - 1)*size_s;
  261. for (s = 0; s < size_s - 2; s++)
  262. {
  263. // Inverted ordering from bottom cap.
  264. index[count++] = offset + size_s - 1;
  265. index[count++] = offset + s;
  266. index[count++] = offset + s + 1;
  267. }
  268. }
  269. }
  270. }
  271. else if (hollow)
  272. {
  273. // Closed hollow
  274. // Outer face
  275. for (t = 0; t < size_t - 1; t++)
  276. {
  277. for (s = 0; s < size_s_out - 1; s++)
  278. {
  279. i  = s + t*size_s;
  280. index[count++]  = i; // x,y
  281. index[count++]  = i + 1; // x+1,y
  282. index[count++]  = i + size_s; // x,y+1
  283. index[count++]  = i + size_s; // x,y+1
  284. index[count++]  = i + 1; // x+1,y
  285. index[count++]  = i + 1 + size_s; // x+1,y+1
  286. }
  287. }
  288. // Inner face
  289. // Invert facing from outer face
  290. for (t = 0; t < size_t - 1; t++)
  291. {
  292. for (s = size_s_out; s < size_s - 1; s++)
  293. {
  294. i  = s + t*size_s;
  295. index[count++]  = i; // x,y
  296. index[count++]  = i + 1; // x+1,y
  297. index[count++]  = i + size_s; // x,y+1
  298. index[count++]  = i + size_s; // x,y+1
  299. index[count++]  = i + 1; // x+1,y
  300. index[count++]  = i + 1 + size_s; // x+1,y+1
  301. }
  302. }
  303. // Do the top and bottom caps, if necessary
  304. if (path_open)
  305. {
  306. // Top cap
  307. S32 pt1 = 0;
  308. S32 pt2 = size_s-1;
  309. S32 i   = (size_t - 1)*size_s;
  310. while (pt2 - pt1 > 1)
  311. {
  312. // Use the profile points instead of the mesh, since you want
  313. // the un-transformed profile distances.
  314. LLVector3 p1 = getProfile().mProfile[pt1];
  315. LLVector3 p2 = getProfile().mProfile[pt2];
  316. LLVector3 pa = getProfile().mProfile[pt1+1];
  317. LLVector3 pb = getProfile().mProfile[pt2-1];
  318. p1.mV[VZ] = 0.f;
  319. p2.mV[VZ] = 0.f;
  320. pa.mV[VZ] = 0.f;
  321. pb.mV[VZ] = 0.f;
  322. // Use area of triangle to determine backfacing
  323. F32 area_1a2, area_1ba, area_21b, area_2ab;
  324. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  325. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  326. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  327. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  328. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  329. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  330. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  331. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  332. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  333. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  334. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  335. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  336. BOOL use_tri1a2 = TRUE;
  337. BOOL tri_1a2 = TRUE;
  338. BOOL tri_21b = TRUE;
  339. if (area_1a2 < 0)
  340. {
  341. tri_1a2 = FALSE;
  342. }
  343. if (area_2ab < 0)
  344. {
  345. // Can't use, because it contains point b
  346. tri_1a2 = FALSE;
  347. }
  348. if (area_21b < 0)
  349. {
  350. tri_21b = FALSE;
  351. }
  352. if (area_1ba < 0)
  353. {
  354. // Can't use, because it contains point b
  355. tri_21b = FALSE;
  356. }
  357. if (!tri_1a2)
  358. {
  359. use_tri1a2 = FALSE;
  360. }
  361. else if (!tri_21b)
  362. {
  363. use_tri1a2 = TRUE;
  364. }
  365. else
  366. {
  367. LLVector3 d1 = p1 - pa;
  368. LLVector3 d2 = p2 - pb;
  369. if (d1.magVecSquared() < d2.magVecSquared())
  370. {
  371. use_tri1a2 = TRUE;
  372. }
  373. else
  374. {
  375. use_tri1a2 = FALSE;
  376. }
  377. }
  378. if (use_tri1a2)
  379. {
  380. index[count++] = pt1 + i;
  381. index[count++] = pt1 + 1 + i;
  382. index[count++] = pt2 + i;
  383. pt1++;
  384. }
  385. else
  386. {
  387. index[count++] = pt1 + i;
  388. index[count++] = pt2 - 1 + i;
  389. index[count++] = pt2 + i;
  390. pt2--;
  391. }
  392. }
  393. // Bottom cap
  394. pt1          = 0;
  395. pt2          = size_s-1;
  396. while (pt2 - pt1 > 1)
  397. {
  398. // Use the profile points instead of the mesh, since you want
  399. // the un-transformed profile distances.
  400. LLVector3 p1 = getProfile().mProfile[pt1];
  401. LLVector3 p2 = getProfile().mProfile[pt2];
  402. LLVector3 pa = getProfile().mProfile[pt1+1];
  403. LLVector3 pb = getProfile().mProfile[pt2-1];
  404. p1.mV[VZ] = 0.f;
  405. p2.mV[VZ] = 0.f;
  406. pa.mV[VZ] = 0.f;
  407. pb.mV[VZ] = 0.f;
  408. // Use area of triangle to determine backfacing
  409. F32 area_1a2, area_1ba, area_21b, area_2ab;
  410. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  411. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  412. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  413. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  414. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  415. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  416. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  417. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  418. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  419. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  420. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  421. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  422. BOOL use_tri1a2 = TRUE;
  423. BOOL tri_1a2 = TRUE;
  424. BOOL tri_21b = TRUE;
  425. if (area_1a2 < 0)
  426. {
  427. tri_1a2 = FALSE;
  428. }
  429. if (area_2ab < 0)
  430. {
  431. // Can't use, because it contains point b
  432. tri_1a2 = FALSE;
  433. }
  434. if (area_21b < 0)
  435. {
  436. tri_21b = FALSE;
  437. }
  438. if (area_1ba < 0)
  439. {
  440. // Can't use, because it contains point b
  441. tri_21b = FALSE;
  442. }
  443. if (!tri_1a2)
  444. {
  445. use_tri1a2 = FALSE;
  446. }
  447. else if (!tri_21b)
  448. {
  449. use_tri1a2 = TRUE;
  450. }
  451. else
  452. {
  453. LLVector3 d1 = p1 - pa;
  454. LLVector3 d2 = p2 - pb;
  455. if (d1.magVecSquared() < d2.magVecSquared())
  456. {
  457. use_tri1a2 = TRUE;
  458. }
  459. else
  460. {
  461. use_tri1a2 = FALSE;
  462. }
  463. }
  464. if (use_tri1a2)
  465. {
  466. index[count++] = pt1;
  467. index[count++] = pt2;
  468. index[count++] = pt1 + 1;
  469. pt1++;
  470. }
  471. else
  472. {
  473. index[count++] = pt1;
  474. index[count++] = pt2;
  475. index[count++] = pt2 - 1;
  476. pt2--;
  477. }
  478. }
  479. }
  480. }
  481. else
  482. {
  483. // Closed solid.  Easy case.
  484. for (t = 0; t < size_t - 1; t++)
  485. {
  486. for (s = 0; s < size_s - 1; s++)
  487. {
  488. // Should wrap properly, but for now...
  489. i  = s + t*size_s;
  490. index[count++]  = i; // x,y
  491. index[count++]  = i + 1; // x+1,y
  492. index[count++]  = i + size_s; // x,y+1
  493. index[count++]  = i + size_s; // x,y+1
  494. index[count++]  = i + 1; // x+1,y
  495. index[count++]  = i + size_s + 1; // x+1,y+1
  496. }
  497. }
  498. // Do the top and bottom caps, if necessary
  499. if (path_open)
  500. {
  501. // bottom cap
  502. for (s = 1; s < size_s - 2; s++)
  503. {
  504. index[count++] = s+1;
  505. index[count++] = s;
  506. index[count++] = 0;
  507. }
  508. // top cap
  509. S32 offset = (size_t - 1)*size_s;
  510. for (s = 1; s < size_s - 2; s++)
  511. {
  512. // Inverted ordering from bottom cap.
  513. index[count++] = offset;
  514. index[count++] = offset + s;
  515. index[count++] = offset + s + 1;
  516. }
  517. }
  518. }
  519. #ifdef LL_DEBUG
  520. // assert that we computed the correct number of indices
  521. if (count != expected_num_triangle_indices )
  522. {
  523. llerrs << "bad index count prediciton:"
  524. << "  expected=" << expected_num_triangle_indices 
  525. << " actual=" << count << llendl;
  526. }
  527. #endif
  528. #if 0
  529. // verify that each index does not point beyond the size of the mesh
  530. S32 num_vertices = mMesh.size();
  531. for (i = 0; i < count; i+=3)
  532. {
  533. llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl;
  534. llassert(index[i] < num_vertices);
  535. llassert(index[i+1] < num_vertices);
  536. llassert(index[i+2] < num_vertices);
  537. }
  538. #endif
  539. num_indices = count;
  540. return index;
  541. }
  542. S32 LLVolume::getNumTriangleIndices() const
  543. {
  544. BOOL profile_open = getProfile().isOpen();
  545. BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
  546. BOOL path_open = getPath().isOpen();
  547. S32 size_s, size_s_out, size_t;
  548. size_s = getProfile().getTotal();
  549. size_s_out = getProfile().getTotalOut();
  550. size_t = getPath().mPath.size();
  551. S32 count = 0;
  552. if (profile_open) /* Flawfinder: ignore */
  553. {
  554. if (hollow)
  555. {
  556. // Open hollow -- much like the closed solid, except we 
  557. // we need to stitch up the gap between s=0 and s=size_s-1
  558. count = (size_t - 1) * (((size_s -1) * 6) + 6);
  559. }
  560. else
  561. {
  562. count = (size_t - 1) * (((size_s -1) * 6) + 6); 
  563. }
  564. }
  565. else if (hollow)
  566. {
  567. // Closed hollow
  568. // Outer face
  569. count = (size_t - 1) * (size_s_out - 1) * 6;
  570. // Inner face
  571. count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6;
  572. }
  573. else
  574. {
  575. // Closed solid.  Easy case.
  576. count = (size_t - 1) * (size_s - 1) * 6;
  577. }
  578. if (path_open)
  579. {
  580. S32 cap_triangle_count = size_s - 3;
  581. if ( profile_open
  582. || hollow )
  583. {
  584. cap_triangle_count = size_s - 2;
  585. }
  586. if ( cap_triangle_count > 0 )
  587. {
  588. // top and bottom caps
  589. count += cap_triangle_count * 2 * 3;
  590. }
  591. }
  592. return count;
  593. }
  594. //-----------------------------------------------------------------------------
  595. // generateSilhouetteVertices()
  596. //-----------------------------------------------------------------------------
  597. void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
  598.   std::vector<LLVector3> &normals,
  599.   std::vector<S32> &segments,
  600.   const LLVector3& obj_cam_vec,
  601.   const LLMatrix4& mat,
  602.   const LLMatrix3& norm_mat,
  603.   S32 face_mask)
  604. {
  605. LLMemType m1(LLMemType::MTYPE_VOLUME);
  606. vertices.clear();
  607. normals.clear();
  608. segments.clear();
  609. S32 cur_index = 0;
  610. //for each face
  611. for (face_list_t::iterator iter = mVolumeFaces.begin();
  612.  iter != mVolumeFaces.end(); ++iter)
  613. {
  614. const LLVolumeFace& face = *iter;
  615. if (!(face_mask & (0x1 << cur_index++)))
  616. {
  617. continue;
  618. }
  619. if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
  620. }
  621. else {
  622. //==============================================
  623. //DEBUG draw edge map instead of silhouette edge
  624. //==============================================
  625. #if DEBUG_SILHOUETTE_EDGE_MAP
  626. //for each triangle
  627. U32 count = face.mIndices.size();
  628. for (U32 j = 0; j < count/3; j++) {
  629. //get vertices
  630. S32 v1 = face.mIndices[j*3+0];
  631. S32 v2 = face.mIndices[j*3+1];
  632. S32 v3 = face.mIndices[j*3+2];
  633. //get current face center
  634. LLVector3 cCenter = (face.mVertices[v1].mPosition + 
  635. face.mVertices[v2].mPosition + 
  636. face.mVertices[v3].mPosition) / 3.0f;
  637. //for each edge
  638. for (S32 k = 0; k < 3; k++) {
  639.                     S32 nIndex = face.mEdge[j*3+k];
  640. if (nIndex <= -1) {
  641. continue;
  642. }
  643. if (nIndex >= (S32) count/3) {
  644. continue;
  645. }
  646. //get neighbor vertices
  647. v1 = face.mIndices[nIndex*3+0];
  648. v2 = face.mIndices[nIndex*3+1];
  649. v3 = face.mIndices[nIndex*3+2];
  650. //get neighbor face center
  651. LLVector3 nCenter = (face.mVertices[v1].mPosition + 
  652. face.mVertices[v2].mPosition + 
  653. face.mVertices[v3].mPosition) / 3.0f;
  654. //draw line
  655. vertices.push_back(cCenter);
  656. vertices.push_back(nCenter);
  657. normals.push_back(LLVector3(1,1,1));
  658. normals.push_back(LLVector3(1,1,1));
  659. segments.push_back(vertices.size());
  660. }
  661. }
  662. continue;
  663. //==============================================
  664. //DEBUG
  665. //==============================================
  666. //==============================================
  667. //DEBUG draw normals instead of silhouette edge
  668. //==============================================
  669. #elif DEBUG_SILHOUETTE_NORMALS
  670. //for each vertex
  671. for (U32 j = 0; j < face.mVertices.size(); j++) {
  672. vertices.push_back(face.mVertices[j].mPosition);
  673. vertices.push_back(face.mVertices[j].mPosition + face.mVertices[j].mNormal*0.1f);
  674. normals.push_back(LLVector3(0,0,1));
  675. normals.push_back(LLVector3(0,0,1));
  676. segments.push_back(vertices.size());
  677. #if DEBUG_SILHOUETTE_BINORMALS
  678. vertices.push_back(face.mVertices[j].mPosition);
  679. vertices.push_back(face.mVertices[j].mPosition + face.mVertices[j].mBinormal*0.1f);
  680. normals.push_back(LLVector3(0,0,1));
  681. normals.push_back(LLVector3(0,0,1));
  682. segments.push_back(vertices.size());
  683. #endif
  684. }
  685. continue;
  686. #else
  687. //==============================================
  688. //DEBUG
  689. //==============================================
  690. static const U8 AWAY = 0x01,
  691. TOWARDS = 0x02;
  692. //for each triangle
  693. std::vector<U8> fFacing;
  694. vector_append(fFacing, face.mIndices.size()/3);
  695. for (U32 j = 0; j < face.mIndices.size()/3; j++) 
  696. {
  697. //approximate normal
  698. S32 v1 = face.mIndices[j*3+0];
  699. S32 v2 = face.mIndices[j*3+1];
  700. S32 v3 = face.mIndices[j*3+2];
  701. LLVector3 norm = (face.mVertices[v1].mPosition - face.mVertices[v2].mPosition) % 
  702. (face.mVertices[v2].mPosition - face.mVertices[v3].mPosition);
  703. if (norm.magVecSquared() < 0.00000001f) 
  704. {
  705. fFacing[j] = AWAY | TOWARDS;
  706. }
  707. else 
  708. {
  709. //get view vector
  710. LLVector3 view = (obj_cam_vec-face.mVertices[v1].mPosition);
  711. bool away = view * norm > 0.0f; 
  712. if (away) 
  713. {
  714. fFacing[j] = AWAY;
  715. }
  716. else 
  717. {
  718. fFacing[j] = TOWARDS;
  719. }
  720. }
  721. }
  722. //for each triangle
  723. for (U32 j = 0; j < face.mIndices.size()/3; j++) 
  724. {
  725. if (fFacing[j] == (AWAY | TOWARDS)) 
  726. { //this is a degenerate triangle
  727. //take neighbor facing (degenerate faces get facing of one of their neighbors)
  728. // *FIX IF NEEDED:  this does not deal with neighboring degenerate faces
  729. for (S32 k = 0; k < 3; k++) 
  730. {
  731. S32 index = face.mEdge[j*3+k];
  732. if (index != -1) 
  733. {
  734. fFacing[j] = fFacing[index];
  735. break;
  736. }
  737. }
  738. continue; //skip degenerate face
  739. }
  740. //for each edge
  741. for (S32 k = 0; k < 3; k++) {
  742. S32 index = face.mEdge[j*3+k];
  743. if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) {
  744. //our neighbor is degenerate, make him face our direction
  745. fFacing[face.mEdge[j*3+k]] = fFacing[j];
  746. continue;
  747. }
  748. if (index == -1 || //edge has no neighbor, MUST be a silhouette edge
  749. (fFacing[index] & fFacing[j]) == 0) {  //we found a silhouette edge
  750. S32 v1 = face.mIndices[j*3+k];
  751. S32 v2 = face.mIndices[j*3+((k+1)%3)];
  752. vertices.push_back(face.mVertices[v1].mPosition*mat);
  753. LLVector3 norm1 = face.mVertices[v1].mNormal * norm_mat;
  754. norm1.normVec();
  755. normals.push_back(norm1);
  756. vertices.push_back(face.mVertices[v2].mPosition*mat);
  757. LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat;
  758. norm2.normVec();
  759. normals.push_back(norm2);
  760. segments.push_back(vertices.size());
  761. }
  762. }
  763. }
  764. #endif
  765. }
  766. }
  767. }
  768. S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, 
  769.    S32 face,
  770.    LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal)
  771. {
  772. S32 hit_face = -1;
  773. S32 start_face;
  774. S32 end_face;
  775. if (face == -1) // ALL_SIDES
  776. {
  777. start_face = 0;
  778. end_face = getNumVolumeFaces() - 1;
  779. }
  780. else
  781. {
  782. start_face = face;
  783. end_face = face;
  784. }
  785. LLVector3 dir = end - start;
  786. F32 closest_t = 2.f; // must be larger than 1
  787. for (S32 i = start_face; i <= end_face; i++)
  788. {
  789. const LLVolumeFace &face = getVolumeFace((U32)i);
  790. LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f;
  791. LLVector3 box_size   = face.mExtents[1] - face.mExtents[0];
  792.         if (LLLineSegmentBoxIntersect(start, end, box_center, box_size))
  793. {
  794. if (bi_normal != NULL) // if the caller wants binormals, we may need to generate them
  795. {
  796. genBinormals(i);
  797. }
  798. for (U32 tri = 0; tri < face.mIndices.size()/3; tri++) 
  799. {
  800. S32 index1 = face.mIndices[tri*3+0];
  801. S32 index2 = face.mIndices[tri*3+1];
  802. S32 index3 = face.mIndices[tri*3+2];
  803. F32 a, b, t;
  804. if (LLTriangleRayIntersect(face.mVertices[index1].mPosition,
  805.    face.mVertices[index2].mPosition,
  806.    face.mVertices[index3].mPosition,
  807.    start, dir, &a, &b, &t, FALSE))
  808. {
  809. if ((t >= 0.f) &&      // if hit is after start
  810. (t <= 1.f) &&      // and before end
  811. (t < closest_t))   // and this hit is closer
  812. {
  813. closest_t = t;
  814. hit_face = i;
  815. if (intersection != NULL)
  816. {
  817. *intersection = start + dir * closest_t;
  818. }
  819. if (tex_coord != NULL)
  820. {
  821. *tex_coord = ((1.f - a - b)  * face.mVertices[index1].mTexCoord +
  822.   a              * face.mVertices[index2].mTexCoord +
  823.   b              * face.mVertices[index3].mTexCoord);
  824. }
  825. if (normal != NULL)
  826. {
  827. *normal    = ((1.f - a - b)  * face.mVertices[index1].mNormal + 
  828.   a              * face.mVertices[index2].mNormal +
  829.   b              * face.mVertices[index3].mNormal);
  830. }
  831. if (bi_normal != NULL)
  832. {
  833. *bi_normal = ((1.f - a - b)  * face.mVertices[index1].mBinormal + 
  834.   a              * face.mVertices[index2].mBinormal +
  835.   b              * face.mVertices[index3].mBinormal);
  836. }
  837. }
  838. }
  839. }
  840. }
  841. }
  842. return hit_face;
  843. }
  844. class LLVertexIndexPair
  845. {
  846. public:
  847. LLVertexIndexPair(const LLVector3 &vertex, const S32 index);
  848. LLVector3 mVertex;
  849. S32 mIndex;
  850. };
  851. LLVertexIndexPair::LLVertexIndexPair(const LLVector3 &vertex, const S32 index)
  852. {
  853. mVertex = vertex;
  854. mIndex = index;
  855. }
  856. const F32 VERTEX_SLOP = 0.00001f;
  857. const F32 VERTEX_SLOP_SQRD = VERTEX_SLOP * VERTEX_SLOP;
  858. struct lessVertex
  859. {
  860. bool operator()(const LLVertexIndexPair *a, const LLVertexIndexPair *b)
  861. {
  862. const F32 slop = VERTEX_SLOP;
  863. if (a->mVertex.mV[0] + slop < b->mVertex.mV[0])
  864. {
  865. return TRUE;
  866. }
  867. else if (a->mVertex.mV[0] - slop > b->mVertex.mV[0])
  868. {
  869. return FALSE;
  870. }
  871. if (a->mVertex.mV[1] + slop < b->mVertex.mV[1])
  872. {
  873. return TRUE;
  874. }
  875. else if (a->mVertex.mV[1] - slop > b->mVertex.mV[1])
  876. {
  877. return FALSE;
  878. }
  879. if (a->mVertex.mV[2] + slop < b->mVertex.mV[2])
  880. {
  881. return TRUE;
  882. }
  883. else if (a->mVertex.mV[2] - slop > b->mVertex.mV[2])
  884. {
  885. return FALSE;
  886. }
  887. return FALSE;
  888. }
  889. };
  890. struct lessTriangle
  891. {
  892. bool operator()(const S32 *a, const S32 *b)
  893. {
  894. if (*a < *b)
  895. {
  896. return TRUE;
  897. }
  898. else if (*a > *b)
  899. {
  900. return FALSE;
  901. }
  902. if (*(a+1) < *(b+1))
  903. {
  904. return TRUE;
  905. }
  906. else if (*(a+1) > *(b+1))
  907. {
  908. return FALSE;
  909. }
  910. if (*(a+2) < *(b+2))
  911. {
  912. return TRUE;
  913. }
  914. else if (*(a+2) > *(b+2))
  915. {
  916. return FALSE;
  917. }
  918. return FALSE;
  919. }
  920. };
  921. BOOL equalTriangle(const S32 *a, const S32 *b)
  922. {
  923. if ((*a == *b) && (*(a+1) == *(b+1)) && (*(a+2) == *(b+2)))
  924. {
  925. return TRUE;
  926. }
  927. return FALSE;
  928. }
  929. BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
  930. const std::vector<Point>& input_vertices,
  931. const S32 num_input_triangles,
  932. S32 *input_triangles,
  933. S32 &num_output_vertices,
  934. LLVector3 **output_vertices,
  935. S32 &num_output_triangles,
  936. S32 **output_triangles)
  937. {
  938. LLMemType m1(LLMemType::MTYPE_VOLUME);
  939. /* Testing: avoid any cleanup
  940. static BOOL skip_cleanup = TRUE;
  941. if ( skip_cleanup )
  942. {
  943. num_output_vertices = num_input_vertices;
  944. num_output_triangles = num_input_triangles;
  945. *output_vertices = new LLVector3[num_input_vertices];
  946. for (S32 index = 0; index < num_input_vertices; index++)
  947. {
  948. (*output_vertices)[index] = input_vertices[index].mPos;
  949. }
  950. *output_triangles = new S32[num_input_triangles*3];
  951. memcpy(*output_triangles, input_triangles, 3*num_input_triangles*sizeof(S32)); // Flawfinder: ignore
  952. return TRUE;
  953. }
  954. */
  955. // Here's how we do this:
  956. // Create a structure which contains the original vertex index and the
  957. // LLVector3 data.
  958. // "Sort" the data by the vectors
  959. // Create an array the size of the old vertex list, with a mapping of
  960. // old indices to new indices.
  961. // Go through triangles, shift so the lowest index is first
  962. // Sort triangles by first index
  963. // Remove duplicate triangles
  964. // Allocate and pack new triangle data.
  965. //LLTimer cleanupTimer;
  966. //llinfos << "In vertices: " << num_input_vertices << llendl;
  967. //llinfos << "In triangles: " << num_input_triangles << llendl;
  968. S32 i;
  969. typedef std::multiset<LLVertexIndexPair*, lessVertex> vertex_set_t;
  970. vertex_set_t vertex_list;
  971. LLVertexIndexPair *pairp = NULL;
  972. for (i = 0; i < num_input_vertices; i++)
  973. {
  974. LLVertexIndexPair *new_pairp = new LLVertexIndexPair(input_vertices[i].mPos, i);
  975. vertex_list.insert(new_pairp);
  976. }
  977. // Generate the vertex mapping and the list of vertices without
  978. // duplicates.  This will crash if there are no vertices.
  979. llassert(num_input_vertices > 0); // check for no vertices!
  980. S32 *vertex_mapping = new S32[num_input_vertices];
  981. LLVector3 *new_vertices = new LLVector3[num_input_vertices];
  982. LLVertexIndexPair *prev_pairp = NULL;
  983. S32 new_num_vertices;
  984. new_num_vertices = 0;
  985. for (vertex_set_t::iterator iter = vertex_list.begin(),
  986.  end = vertex_list.end();
  987.  iter != end; iter++)
  988. {
  989. pairp = *iter;
  990. if (!prev_pairp || ((pairp->mVertex - prev_pairp->mVertex).magVecSquared() >= VERTEX_SLOP_SQRD))
  991. {
  992. new_vertices[new_num_vertices] = pairp->mVertex;
  993. //llinfos << "Added vertex " << new_num_vertices << " : " << pairp->mVertex << llendl;
  994. new_num_vertices++;
  995. // Update the previous
  996. prev_pairp = pairp;
  997. }
  998. else
  999. {
  1000. //llinfos << "Removed duplicate vertex " << pairp->mVertex << ", distance magVecSquared() is " << (pairp->mVertex - prev_pairp->mVertex).magVecSquared() << llendl;
  1001. }
  1002. vertex_mapping[pairp->mIndex] = new_num_vertices - 1;
  1003. }
  1004. // Iterate through triangles and remove degenerates, re-ordering vertices
  1005. // along the way.
  1006. S32 *new_triangles = new S32[num_input_triangles * 3];
  1007. S32 new_num_triangles = 0;
  1008. for (i = 0; i < num_input_triangles; i++)
  1009. {
  1010. S32 v1 = i*3;
  1011. S32 v2 = v1 + 1;
  1012. S32 v3 = v1 + 2;
  1013. //llinfos << "Checking triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl;
  1014. input_triangles[v1] = vertex_mapping[input_triangles[v1]];
  1015. input_triangles[v2] = vertex_mapping[input_triangles[v2]];
  1016. input_triangles[v3] = vertex_mapping[input_triangles[v3]];
  1017. if ((input_triangles[v1] == input_triangles[v2])
  1018. || (input_triangles[v1] == input_triangles[v3])
  1019. || (input_triangles[v2] == input_triangles[v3]))
  1020. {
  1021. //llinfos << "Removing degenerate triangle " << input_triangles[v1] << ":" << input_triangles[v2] << ":" << input_triangles[v3] << llendl;
  1022. // Degenerate triangle, skip
  1023. continue;
  1024. }
  1025. if (input_triangles[v1] < input_triangles[v2])
  1026. {
  1027. if (input_triangles[v1] < input_triangles[v3])
  1028. {
  1029. // (0 < 1) && (0 < 2)
  1030. new_triangles[new_num_triangles*3] = input_triangles[v1];
  1031. new_triangles[new_num_triangles*3+1] = input_triangles[v2];
  1032. new_triangles[new_num_triangles*3+2] = input_triangles[v3];
  1033. }
  1034. else
  1035. {
  1036. // (0 < 1) && (2 < 0)
  1037. new_triangles[new_num_triangles*3] = input_triangles[v3];
  1038. new_triangles[new_num_triangles*3+1] = input_triangles[v1];
  1039. new_triangles[new_num_triangles*3+2] = input_triangles[v2];
  1040. }
  1041. }
  1042. else if (input_triangles[v2] < input_triangles[v3])
  1043. {
  1044. // (1 < 0) && (1 < 2)
  1045. new_triangles[new_num_triangles*3] = input_triangles[v2];
  1046. new_triangles[new_num_triangles*3+1] = input_triangles[v3];
  1047. new_triangles[new_num_triangles*3+2] = input_triangles[v1];
  1048. }
  1049. else
  1050. {
  1051. // (1 < 0) && (2 < 1)
  1052. new_triangles[new_num_triangles*3] = input_triangles[v3];
  1053. new_triangles[new_num_triangles*3+1] = input_triangles[v1];
  1054. new_triangles[new_num_triangles*3+2] = input_triangles[v2];
  1055. }
  1056. new_num_triangles++;
  1057. }
  1058. if (new_num_triangles == 0)
  1059. {
  1060. llwarns << "Created volume object with 0 faces." << llendl;
  1061. delete[] new_triangles;
  1062. delete[] vertex_mapping;
  1063. delete[] new_vertices;
  1064. return FALSE;
  1065. }
  1066. typedef std::set<S32*, lessTriangle> triangle_set_t;
  1067. triangle_set_t triangle_list;
  1068. for (i = 0; i < new_num_triangles; i++)
  1069. {
  1070. triangle_list.insert(&new_triangles[i*3]);
  1071. }
  1072. // Sort through the triangle list, and delete duplicates
  1073. S32 *prevp = NULL;
  1074. S32 *curp = NULL;
  1075. S32 *sorted_tris = new S32[new_num_triangles*3];
  1076. S32 cur_tri = 0;
  1077. for (triangle_set_t::iterator iter = triangle_list.begin(),
  1078.  end = triangle_list.end();
  1079.  iter != end; iter++)
  1080. {
  1081. curp = *iter;
  1082. if (!prevp || !equalTriangle(prevp, curp))
  1083. {
  1084. //llinfos << "Added triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl;
  1085. sorted_tris[cur_tri*3] = *curp;
  1086. sorted_tris[cur_tri*3+1] = *(curp+1);
  1087. sorted_tris[cur_tri*3+2] = *(curp+2);
  1088. cur_tri++;
  1089. prevp = curp;
  1090. }
  1091. else
  1092. {
  1093. //llinfos << "Skipped triangle " << *curp << ":" << *(curp+1) << ":" << *(curp+2) << llendl;
  1094. }
  1095. }
  1096. *output_vertices = new LLVector3[new_num_vertices];
  1097. num_output_vertices = new_num_vertices;
  1098. for (i = 0; i < new_num_vertices; i++)
  1099. {
  1100. (*output_vertices)[i] = new_vertices[i];
  1101. }
  1102. *output_triangles = new S32[cur_tri*3];
  1103. num_output_triangles = cur_tri;
  1104. memcpy(*output_triangles, sorted_tris, 3*cur_tri*sizeof(S32)); /* Flawfinder: ignore */
  1105. /*
  1106. llinfos << "Out vertices: " << num_output_vertices << llendl;
  1107. llinfos << "Out triangles: " << num_output_triangles << llendl;
  1108. for (i = 0; i < num_output_vertices; i++)
  1109. {
  1110. llinfos << i << ":" << (*output_vertices)[i] << llendl;
  1111. }
  1112. for (i = 0; i < num_output_triangles; i++)
  1113. {
  1114. llinfos << i << ":" << (*output_triangles)[i*3] << ":" << (*output_triangles)[i*3+1] << ":" << (*output_triangles)[i*3+2] << llendl;
  1115. }
  1116. */
  1117. //llinfos << "Out vertices: " << num_output_vertices << llendl;
  1118. //llinfos << "Out triangles: " << num_output_triangles << llendl;
  1119. delete[] vertex_mapping;
  1120. vertex_mapping = NULL;
  1121. delete[] new_vertices;
  1122. new_vertices = NULL;
  1123. delete[] new_triangles;
  1124. new_triangles = NULL;
  1125. delete[] sorted_tris;
  1126. sorted_tris = NULL;
  1127. triangle_list.clear();
  1128. std::for_each(vertex_list.begin(), vertex_list.end(), DeletePointer());
  1129. vertex_list.clear();
  1130. return TRUE;
  1131. }
  1132. BOOL LLVolumeParams::importFile(LLFILE *fp)
  1133. {
  1134. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1135. //llinfos << "importing volume" << llendl;
  1136. const S32 BUFSIZE = 16384;
  1137. char buffer[BUFSIZE]; /* Flawfinder: ignore */
  1138. // *NOTE: changing the size or type of this buffer will require
  1139. // changing the sscanf below.
  1140. char keyword[256]; /* Flawfinder: ignore */
  1141. keyword[0] = 0;
  1142. while (!feof(fp))
  1143. {
  1144. if (fgets(buffer, BUFSIZE, fp) == NULL)
  1145. {
  1146. buffer[0] = '';
  1147. }
  1148. sscanf(buffer, " %255s", keyword); /* Flawfinder: ignore */
  1149. if (!strcmp("{", keyword))
  1150. {
  1151. continue;
  1152. }
  1153. if (!strcmp("}",keyword))
  1154. {
  1155. break;
  1156. }
  1157. else if (!strcmp("profile", keyword))
  1158. {
  1159. mProfileParams.importFile(fp);
  1160. }
  1161. else if (!strcmp("path",keyword))
  1162. {
  1163. mPathParams.importFile(fp);
  1164. }
  1165. else
  1166. {
  1167. llwarns << "unknown keyword " << keyword << " in volume import" << llendl;
  1168. }
  1169. }
  1170. return TRUE;
  1171. }
  1172. BOOL LLVolumeParams::exportFile(LLFILE *fp) const
  1173. {
  1174. fprintf(fp,"tshape 0n");
  1175. fprintf(fp,"t{n");
  1176. mPathParams.exportFile(fp);
  1177. mProfileParams.exportFile(fp);
  1178. fprintf(fp, "t}n");
  1179. return TRUE;
  1180. }
  1181. BOOL LLVolumeParams::importLegacyStream(std::istream& input_stream)
  1182. {
  1183. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1184. //llinfos << "importing volume" << llendl;
  1185. const S32 BUFSIZE = 16384;
  1186. // *NOTE: changing the size or type of this buffer will require
  1187. // changing the sscanf below.
  1188. char buffer[BUFSIZE]; /* Flawfinder: ignore */
  1189. char keyword[256]; /* Flawfinder: ignore */
  1190. keyword[0] = 0;
  1191. while (input_stream.good())
  1192. {
  1193. input_stream.getline(buffer, BUFSIZE);
  1194. sscanf(buffer, " %255s", keyword);
  1195. if (!strcmp("{", keyword))
  1196. {
  1197. continue;
  1198. }
  1199. if (!strcmp("}",keyword))
  1200. {
  1201. break;
  1202. }
  1203. else if (!strcmp("profile", keyword))
  1204. {
  1205. mProfileParams.importLegacyStream(input_stream);
  1206. }
  1207. else if (!strcmp("path",keyword))
  1208. {
  1209. mPathParams.importLegacyStream(input_stream);
  1210. }
  1211. else
  1212. {
  1213. llwarns << "unknown keyword " << keyword << " in volume import" << llendl;
  1214. }
  1215. }
  1216. return TRUE;
  1217. }
  1218. BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const
  1219. {
  1220. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1221. output_stream <<"tshape 0n";
  1222. output_stream <<"t{n";
  1223. mPathParams.exportLegacyStream(output_stream);
  1224. mProfileParams.exportLegacyStream(output_stream);
  1225. output_stream << "t}n";
  1226. return TRUE;
  1227. }
  1228. LLSD LLVolumeParams::asLLSD() const
  1229. {
  1230. LLSD sd = LLSD();
  1231. sd["path"] = mPathParams;
  1232. sd["profile"] = mProfileParams;
  1233. return sd;
  1234. }
  1235. bool LLVolumeParams::fromLLSD(LLSD& sd)
  1236. {
  1237. mPathParams.fromLLSD(sd["path"]);
  1238. mProfileParams.fromLLSD(sd["profile"]);
  1239. return true;
  1240. }
  1241. void LLVolumeParams::reduceS(F32 begin, F32 end)
  1242. {
  1243. begin = llclampf(begin);
  1244. end = llclampf(end);
  1245. if (begin > end)
  1246. {
  1247. F32 temp = begin;
  1248. begin = end;
  1249. end = temp;
  1250. }
  1251. F32 a = mProfileParams.getBegin();
  1252. F32 b = mProfileParams.getEnd();
  1253. mProfileParams.setBegin(a + begin * (b - a));
  1254. mProfileParams.setEnd(a + end * (b - a));
  1255. }
  1256. void LLVolumeParams::reduceT(F32 begin, F32 end)
  1257. {
  1258. begin = llclampf(begin);
  1259. end = llclampf(end);
  1260. if (begin > end)
  1261. {
  1262. F32 temp = begin;
  1263. begin = end;
  1264. end = temp;
  1265. }
  1266. F32 a = mPathParams.getBegin();
  1267. F32 b = mPathParams.getEnd();
  1268. mPathParams.setBegin(a + begin * (b - a));
  1269. mPathParams.setEnd(a + end * (b - a));
  1270. }
  1271. const F32 MIN_CONCAVE_PROFILE_WEDGE = 0.125f; // 1/8 unity
  1272. const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity
  1273. // returns TRUE if the shape can be approximated with a convex shape 
  1274. // for collison purposes
  1275. BOOL LLVolumeParams::isConvex() const
  1276. {
  1277. F32 path_length = mPathParams.getEnd() - mPathParams.getBegin();
  1278. F32 hollow = mProfileParams.getHollow();
  1279.  
  1280. U8 path_type = mPathParams.getCurveType();
  1281. if ( path_length > MIN_CONCAVE_PATH_WEDGE
  1282. && ( mPathParams.getTwist() != mPathParams.getTwistBegin()
  1283.      || (hollow > 0.f 
  1284.  && LL_PCODE_PATH_LINE != path_type) ) )
  1285. {
  1286. // twist along a "not too short" path is concave
  1287. return FALSE;
  1288. }
  1289. F32 profile_length = mProfileParams.getEnd() - mProfileParams.getBegin();
  1290. BOOL same_hole = hollow == 0.f 
  1291.  || (mProfileParams.getCurveType() & LL_PCODE_HOLE_MASK) == LL_PCODE_HOLE_SAME;
  1292. F32 min_profile_wedge = MIN_CONCAVE_PROFILE_WEDGE;
  1293. U8 profile_type = mProfileParams.getCurveType() & LL_PCODE_PROFILE_MASK;
  1294. if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type )
  1295. {
  1296. // it is a sphere and spheres get twice the minimum profile wedge
  1297. min_profile_wedge = 2.f * MIN_CONCAVE_PROFILE_WEDGE;
  1298. }
  1299. BOOL convex_profile = ( ( profile_length == 1.f
  1300.      || profile_length <= 0.5f )
  1301.    && hollow == 0.f ) // trivially convex
  1302.   || ( profile_length <= min_profile_wedge
  1303.   && same_hole ); // effectvely convex (even when hollow)
  1304. if (!convex_profile)
  1305. {
  1306. // profile is concave
  1307. return FALSE;
  1308. }
  1309. if ( LL_PCODE_PATH_LINE == path_type )
  1310. {
  1311. // straight paths with convex profile
  1312. return TRUE;
  1313. }
  1314. BOOL concave_path = (path_length < 1.0f) && (path_length > 0.5f);
  1315. if (concave_path)
  1316. {
  1317. return FALSE;
  1318. }
  1319. // we're left with spheres, toroids and tubes
  1320. if ( LL_PCODE_PROFILE_CIRCLE_HALF == profile_type )
  1321. {
  1322. // at this stage all spheres must be convex
  1323. return TRUE;
  1324. }
  1325. // it's a toroid or tube
  1326. if ( path_length <= MIN_CONCAVE_PATH_WEDGE )
  1327. {
  1328. // effectively convex
  1329. return TRUE;
  1330. }
  1331. return FALSE;
  1332. }
  1333. // debug
  1334. void LLVolumeParams::setCube()
  1335. {
  1336. mProfileParams.setCurveType(LL_PCODE_PROFILE_SQUARE);
  1337. mProfileParams.setBegin(0.f);
  1338. mProfileParams.setEnd(1.f);
  1339. mProfileParams.setHollow(0.f);
  1340. mPathParams.setBegin(0.f);
  1341. mPathParams.setEnd(1.f);
  1342. mPathParams.setScale(1.f, 1.f);
  1343. mPathParams.setShear(0.f, 0.f);
  1344. mPathParams.setCurveType(LL_PCODE_PATH_LINE);
  1345. mPathParams.setTwistBegin(0.f);
  1346. mPathParams.setTwistEnd(0.f);
  1347. mPathParams.setRadiusOffset(0.f);
  1348. mPathParams.setTaper(0.f, 0.f);
  1349. mPathParams.setRevolutions(0.f);
  1350. mPathParams.setSkew(0.f);
  1351. }
  1352. LLFaceID LLVolume::generateFaceMask()
  1353. {
  1354. LLFaceID new_mask = 0x0000;
  1355. switch(mParams.getProfileParams().getCurveType() & LL_PCODE_PROFILE_MASK)
  1356. {
  1357. case LL_PCODE_PROFILE_CIRCLE:
  1358. case LL_PCODE_PROFILE_CIRCLE_HALF:
  1359. new_mask |= LL_FACE_OUTER_SIDE_0;
  1360. break;
  1361. case LL_PCODE_PROFILE_SQUARE:
  1362. {
  1363. for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 4.f); side < llceil(mParams.getProfileParams().getEnd() * 4.f); side++)
  1364. {
  1365. new_mask |= LL_FACE_OUTER_SIDE_0 << side;
  1366. }
  1367. }
  1368. break;
  1369. case LL_PCODE_PROFILE_ISOTRI:
  1370. case LL_PCODE_PROFILE_EQUALTRI:
  1371. case LL_PCODE_PROFILE_RIGHTTRI:
  1372. {
  1373. for(S32 side = (S32)(mParams.getProfileParams().getBegin() * 3.f); side < llceil(mParams.getProfileParams().getEnd() * 3.f); side++)
  1374. {
  1375. new_mask |= LL_FACE_OUTER_SIDE_0 << side;
  1376. }
  1377. }
  1378. break;
  1379. default:
  1380. llerrs << "Unknown profile!" << llendl;
  1381. break;
  1382. }
  1383. // handle hollow objects
  1384. if (mParams.getProfileParams().getHollow() > 0)
  1385. {
  1386. new_mask |= LL_FACE_INNER_SIDE;
  1387. }
  1388. // handle open profile curves
  1389. if (mProfilep->isOpen())
  1390. {
  1391. new_mask |= LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END;
  1392. }
  1393. // handle open path curves
  1394. if (mPathp->isOpen())
  1395. {
  1396. new_mask |= LL_FACE_PATH_BEGIN | LL_FACE_PATH_END;
  1397. }
  1398. return new_mask;
  1399. }
  1400. BOOL LLVolume::isFaceMaskValid(LLFaceID face_mask)
  1401. {
  1402. LLFaceID test_mask = 0;
  1403. for(S32 i = 0; i < getNumFaces(); i++)
  1404. {
  1405. test_mask |= mProfilep->mFaces[i].mFaceID;
  1406. }
  1407. return test_mask == face_mask;
  1408. }
  1409. BOOL LLVolume::isConvex() const
  1410. {
  1411. // mParams.isConvex() may return FALSE even though the final
  1412. // geometry is actually convex due to LOD approximations.
  1413. // TODO -- provide LLPath and LLProfile with isConvex() methods
  1414. // that correctly determine convexity. -- Leviathan
  1415. return mParams.isConvex();
  1416. }
  1417. std::ostream& operator<<(std::ostream &s, const LLProfileParams &profile_params)
  1418. {
  1419. s << "{type=" << (U32) profile_params.mCurveType;
  1420. s << ", begin=" << profile_params.mBegin;
  1421. s << ", end=" << profile_params.mEnd;
  1422. s << ", hollow=" << profile_params.mHollow;
  1423. s << "}";
  1424. return s;
  1425. }
  1426. std::ostream& operator<<(std::ostream &s, const LLPathParams &path_params)
  1427. {
  1428. s << "{type=" << (U32) path_params.mCurveType;
  1429. s << ", begin=" << path_params.mBegin;
  1430. s << ", end=" << path_params.mEnd;
  1431. s << ", twist=" << path_params.mTwistEnd;
  1432. s << ", scale=" << path_params.mScale;
  1433. s << ", shear=" << path_params.mShear;
  1434. s << ", twist_begin=" << path_params.mTwistBegin;
  1435. s << ", radius_offset=" << path_params.mRadiusOffset;
  1436. s << ", taper=" << path_params.mTaper;
  1437. s << ", revolutions=" << path_params.mRevolutions;
  1438. s << ", skew=" << path_params.mSkew;
  1439. s << "}";
  1440. return s;
  1441. }
  1442. std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params)
  1443. {
  1444. s << "{profileparams = " << volume_params.mProfileParams;
  1445. s << ", pathparams = " << volume_params.mPathParams;
  1446. s << "}";
  1447. return s;
  1448. }
  1449. std::ostream& operator<<(std::ostream &s, const LLProfile &profile)
  1450. {
  1451. s << " {open=" << (U32) profile.mOpen;
  1452. s << ", dirty=" << profile.mDirty;
  1453. s << ", totalout=" << profile.mTotalOut;
  1454. s << ", total=" << profile.mTotal;
  1455. s << "}";
  1456. return s;
  1457. }
  1458. std::ostream& operator<<(std::ostream &s, const LLPath &path)
  1459. {
  1460. s << "{open=" << (U32) path.mOpen;
  1461. s << ", dirty=" << path.mDirty;
  1462. s << ", step=" << path.mStep;
  1463. s << ", total=" << path.mTotal;
  1464. s << "}";
  1465. return s;
  1466. }
  1467. std::ostream& operator<<(std::ostream &s, const LLVolume &volume)
  1468. {
  1469. s << "{params = " << volume.getParams();
  1470. s << ", path = " << *volume.mPathp;
  1471. s << ", profile = " << *volume.mProfilep;
  1472. s << "}";
  1473. return s;
  1474. }
  1475. std::ostream& operator<<(std::ostream &s, const LLVolume *volumep)
  1476. {
  1477. s << "{params = " << volumep->getParams();
  1478. s << ", path = " << *(volumep->mPathp);
  1479. s << ", profile = " << *(volumep->mProfilep);
  1480. s << "}";
  1481. return s;
  1482. }
  1483. BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
  1484. {
  1485. if (mTypeMask & CAP_MASK)
  1486. {
  1487. return createCap(volume, partial_build);
  1488. }
  1489. else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
  1490. {
  1491. return createSide(volume, partial_build);
  1492. }
  1493. else
  1494. {
  1495. llerrs << "Unknown/uninitialized face type!" << llendl;
  1496. return FALSE;
  1497. }
  1498. }
  1499. void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
  1500.    LLVolumeFace::VertexData& v1,
  1501.    LLVolumeFace::VertexData& v2,
  1502.    LLVolumeFace::VertexData& vout,
  1503.    F32 coef01,
  1504.    F32 coef02)
  1505. {
  1506. vout.mPosition = v0.mPosition + ((v1.mPosition-v0.mPosition)*coef01)+((v2.mPosition-v0.mPosition)*coef02);
  1507. vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02);
  1508. vout.mNormal = v0.mNormal;
  1509. vout.mBinormal = v0.mBinormal;
  1510. }
  1511. BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
  1512. {
  1513. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1514. const std::vector<LLVolume::Point>& mesh = volume->getMesh();
  1515. const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
  1516. S32 max_s = volume->getProfile().getTotal();
  1517. S32 max_t = volume->getPath().mPath.size();
  1518. // S32 i;
  1519. S32 num_vertices = 0, num_indices = 0;
  1520. S32 grid_size = (profile.size()-1)/4;
  1521. S32 quad_count = (grid_size * grid_size);
  1522. num_vertices = (grid_size+1)*(grid_size+1);
  1523. num_indices = quad_count * 4;
  1524. LLVector3& min = mExtents[0];
  1525. LLVector3& max = mExtents[1];
  1526. S32 offset = 0;
  1527. if (mTypeMask & TOP_MASK)
  1528. offset = (max_t-1) * max_s;
  1529. else
  1530. offset = mBeginS;
  1531. VertexData corners[4];
  1532. VertexData baseVert;
  1533. for(int t = 0; t < 4; t++){
  1534. corners[t].mPosition = mesh[offset + (grid_size*t)].mPos;
  1535. corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f;
  1536. corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1];
  1537. }
  1538. baseVert.mNormal = 
  1539. ((corners[1].mPosition-corners[0].mPosition) % 
  1540. (corners[2].mPosition-corners[1].mPosition));
  1541. baseVert.mNormal.normVec();
  1542. if(!(mTypeMask & TOP_MASK)){
  1543. baseVert.mNormal *= -1.0f;
  1544. }else{
  1545. //Swap the UVs on the U(X) axis for top face
  1546. LLVector2 swap;
  1547. swap = corners[0].mTexCoord;
  1548. corners[0].mTexCoord=corners[3].mTexCoord;
  1549. corners[3].mTexCoord=swap;
  1550. swap = corners[1].mTexCoord;
  1551. corners[1].mTexCoord=corners[2].mTexCoord;
  1552. corners[2].mTexCoord=swap;
  1553. }
  1554. baseVert.mBinormal = calc_binormal_from_triangle( 
  1555. corners[0].mPosition, corners[0].mTexCoord,
  1556. corners[1].mPosition, corners[1].mTexCoord,
  1557. corners[2].mPosition, corners[2].mTexCoord);
  1558. for(int t = 0; t < 4; t++){
  1559. corners[t].mBinormal = baseVert.mBinormal;
  1560. corners[t].mNormal = baseVert.mNormal;
  1561. }
  1562. mHasBinormals = TRUE;
  1563. if (partial_build)
  1564. {
  1565. mVertices.clear();
  1566. }
  1567. S32 vtop = mVertices.size();
  1568. for(int gx = 0;gx<grid_size+1;gx++){
  1569. for(int gy = 0;gy<grid_size+1;gy++){
  1570. VertexData newVert;
  1571. LerpPlanarVertex(
  1572. corners[0],
  1573. corners[1],
  1574. corners[3],
  1575. newVert,
  1576. (F32)gx/(F32)grid_size,
  1577. (F32)gy/(F32)grid_size);
  1578. mVertices.push_back(newVert);
  1579. if (gx == 0 && gy == 0)
  1580. {
  1581. min = max = newVert.mPosition;
  1582. }
  1583. else
  1584. {
  1585. update_min_max(min,max,newVert.mPosition);
  1586. }
  1587. }
  1588. }
  1589. mCenter = (min + max) * 0.5f;
  1590. if (!partial_build)
  1591. {
  1592. int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
  1593. for(int gx = 0;gx<grid_size;gx++){
  1594. for(int gy = 0;gy<grid_size;gy++){
  1595. if (mTypeMask & TOP_MASK){
  1596. for(int i=5;i>=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
  1597. }else{
  1598. for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]);
  1599. }
  1600. }
  1601. }
  1602. }
  1603. return TRUE;
  1604. }
  1605. BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
  1606. {
  1607. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1608. if (!(mTypeMask & HOLLOW_MASK) && 
  1609. !(mTypeMask & OPEN_MASK) && 
  1610. ((volume->getParams().getPathParams().getBegin()==0.0f)&&
  1611. (volume->getParams().getPathParams().getEnd()==1.0f))&&
  1612. (volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE &&
  1613.  volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE)
  1614. ){
  1615. return createUnCutCubeCap(volume, partial_build);
  1616. }
  1617. S32 num_vertices = 0, num_indices = 0;
  1618. const std::vector<LLVolume::Point>& mesh = volume->getMesh();
  1619. const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
  1620. // All types of caps have the same number of vertices and indices
  1621. num_vertices = profile.size();
  1622. num_indices = (profile.size() - 2)*3;
  1623. mVertices.resize(num_vertices);
  1624. if (!partial_build)
  1625. {
  1626. mIndices.resize(num_indices);
  1627. }
  1628. S32 max_s = volume->getProfile().getTotal();
  1629. S32 max_t = volume->getPath().mPath.size();
  1630. mCenter.clearVec();
  1631. S32 offset = 0;
  1632. if (mTypeMask & TOP_MASK)
  1633. {
  1634. offset = (max_t-1) * max_s;
  1635. }
  1636. else
  1637. {
  1638. offset = mBeginS;
  1639. }
  1640. // Figure out the normal, assume all caps are flat faces.
  1641. // Cross product to get normals.
  1642. LLVector2 cuv;
  1643. LLVector2 min_uv, max_uv;
  1644. LLVector3& min = mExtents[0];
  1645. LLVector3& max = mExtents[1];
  1646. // Copy the vertices into the array
  1647. for (S32 i = 0; i < num_vertices; i++)
  1648. {
  1649. if (mTypeMask & TOP_MASK)
  1650. {
  1651. mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f;
  1652. mVertices[i].mTexCoord.mV[1] = profile[i].mV[1]+0.5f;
  1653. }
  1654. else
  1655. {
  1656. // Mirror for underside.
  1657. mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f;
  1658. mVertices[i].mTexCoord.mV[1] = 0.5f - profile[i].mV[1];
  1659. }
  1660. mVertices[i].mPosition = mesh[i + offset].mPos;
  1661. if (i == 0)
  1662. {
  1663. min = max = mVertices[i].mPosition;
  1664. min_uv = max_uv = mVertices[i].mTexCoord;
  1665. }
  1666. else
  1667. {
  1668. update_min_max(min,max, mVertices[i].mPosition);
  1669. update_min_max(min_uv, max_uv, mVertices[i].mTexCoord);
  1670. }
  1671. }
  1672. mCenter = (min+max)*0.5f;
  1673. cuv = (min_uv + max_uv)*0.5f;
  1674. LLVector3 binormal = calc_binormal_from_triangle( 
  1675. mCenter, cuv,
  1676. mVertices[0].mPosition, mVertices[0].mTexCoord,
  1677. mVertices[1].mPosition, mVertices[1].mTexCoord);
  1678. binormal.normVec();
  1679. LLVector3 d0;
  1680. LLVector3 d1;
  1681. LLVector3 normal;
  1682. d0 = mCenter-mVertices[0].mPosition;
  1683. d1 = mCenter-mVertices[1].mPosition;
  1684. normal = (mTypeMask & TOP_MASK) ? (d0%d1) : (d1%d0);
  1685. normal.normVec();
  1686. VertexData vd;
  1687. vd.mPosition = mCenter;
  1688. vd.mNormal = normal;
  1689. vd.mBinormal = binormal;
  1690. vd.mTexCoord = cuv;
  1691. if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK))
  1692. {
  1693. mVertices.push_back(vd);
  1694. num_vertices++;
  1695. if (!partial_build)
  1696. {
  1697. vector_append(mIndices, 3);
  1698. }
  1699. }
  1700. for (S32 i = 0; i < num_vertices; i++)
  1701. {
  1702. mVertices[i].mBinormal = binormal;
  1703. mVertices[i].mNormal = normal;
  1704. }
  1705. mHasBinormals = TRUE;
  1706. if (partial_build)
  1707. {
  1708. return TRUE;
  1709. }
  1710. if (mTypeMask & HOLLOW_MASK)
  1711. {
  1712. if (mTypeMask & TOP_MASK)
  1713. {
  1714. // HOLLOW TOP
  1715. // Does it matter if it's open or closed? - djs
  1716. S32 pt1 = 0, pt2 = num_vertices - 1;
  1717. S32 i = 0;
  1718. while (pt2 - pt1 > 1)
  1719. {
  1720. // Use the profile points instead of the mesh, since you want
  1721. // the un-transformed profile distances.
  1722. LLVector3 p1 = profile[pt1];
  1723. LLVector3 p2 = profile[pt2];
  1724. LLVector3 pa = profile[pt1+1];
  1725. LLVector3 pb = profile[pt2-1];
  1726. p1.mV[VZ] = 0.f;
  1727. p2.mV[VZ] = 0.f;
  1728. pa.mV[VZ] = 0.f;
  1729. pb.mV[VZ] = 0.f;
  1730. // Use area of triangle to determine backfacing
  1731. F32 area_1a2, area_1ba, area_21b, area_2ab;
  1732. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  1733. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  1734. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  1735. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  1736. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  1737. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  1738. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  1739. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  1740. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  1741. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  1742. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  1743. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  1744. BOOL use_tri1a2 = TRUE;
  1745. BOOL tri_1a2 = TRUE;
  1746. BOOL tri_21b = TRUE;
  1747. if (area_1a2 < 0)
  1748. {
  1749. tri_1a2 = FALSE;
  1750. }
  1751. if (area_2ab < 0)
  1752. {
  1753. // Can't use, because it contains point b
  1754. tri_1a2 = FALSE;
  1755. }
  1756. if (area_21b < 0)
  1757. {
  1758. tri_21b = FALSE;
  1759. }
  1760. if (area_1ba < 0)
  1761. {
  1762. // Can't use, because it contains point b
  1763. tri_21b = FALSE;
  1764. }
  1765. if (!tri_1a2)
  1766. {
  1767. use_tri1a2 = FALSE;
  1768. }
  1769. else if (!tri_21b)
  1770. {
  1771. use_tri1a2 = TRUE;
  1772. }
  1773. else
  1774. {
  1775. LLVector3 d1 = p1 - pa;
  1776. LLVector3 d2 = p2 - pb;
  1777. if (d1.magVecSquared() < d2.magVecSquared())
  1778. {
  1779. use_tri1a2 = TRUE;
  1780. }
  1781. else
  1782. {
  1783. use_tri1a2 = FALSE;
  1784. }
  1785. }
  1786. if (use_tri1a2)
  1787. {
  1788. mIndices[i++] = pt1;
  1789. mIndices[i++] = pt1 + 1;
  1790. mIndices[i++] = pt2;
  1791. pt1++;
  1792. }
  1793. else
  1794. {
  1795. mIndices[i++] = pt1;
  1796. mIndices[i++] = pt2 - 1;
  1797. mIndices[i++] = pt2;
  1798. pt2--;
  1799. }
  1800. }
  1801. }
  1802. else
  1803. {
  1804. // HOLLOW BOTTOM
  1805. // Does it matter if it's open or closed? - djs
  1806. llassert(mTypeMask & BOTTOM_MASK);
  1807. S32 pt1 = 0, pt2 = num_vertices - 1;
  1808. S32 i = 0;
  1809. while (pt2 - pt1 > 1)
  1810. {
  1811. // Use the profile points instead of the mesh, since you want
  1812. // the un-transformed profile distances.
  1813. LLVector3 p1 = profile[pt1];
  1814. LLVector3 p2 = profile[pt2];
  1815. LLVector3 pa = profile[pt1+1];
  1816. LLVector3 pb = profile[pt2-1];
  1817. p1.mV[VZ] = 0.f;
  1818. p2.mV[VZ] = 0.f;
  1819. pa.mV[VZ] = 0.f;
  1820. pb.mV[VZ] = 0.f;
  1821. // Use area of triangle to determine backfacing
  1822. F32 area_1a2, area_1ba, area_21b, area_2ab;
  1823. area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  1824. (pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  1825. (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  1826. area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  1827. (pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  1828. (pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  1829. area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  1830. (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  1831. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  1832. area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  1833. (pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  1834. (pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  1835. BOOL use_tri1a2 = TRUE;
  1836. BOOL tri_1a2 = TRUE;
  1837. BOOL tri_21b = TRUE;
  1838. if (area_1a2 < 0)
  1839. {
  1840. tri_1a2 = FALSE;
  1841. }
  1842. if (area_2ab < 0)
  1843. {
  1844. // Can't use, because it contains point b
  1845. tri_1a2 = FALSE;
  1846. }
  1847. if (area_21b < 0)
  1848. {
  1849. tri_21b = FALSE;
  1850. }
  1851. if (area_1ba < 0)
  1852. {
  1853. // Can't use, because it contains point b
  1854. tri_21b = FALSE;
  1855. }
  1856. if (!tri_1a2)
  1857. {
  1858. use_tri1a2 = FALSE;
  1859. }
  1860. else if (!tri_21b)
  1861. {
  1862. use_tri1a2 = TRUE;
  1863. }
  1864. else
  1865. {
  1866. LLVector3 d1 = p1 - pa;
  1867. LLVector3 d2 = p2 - pb;
  1868. if (d1.magVecSquared() < d2.magVecSquared())
  1869. {
  1870. use_tri1a2 = TRUE;
  1871. }
  1872. else
  1873. {
  1874. use_tri1a2 = FALSE;
  1875. }
  1876. }
  1877. // Flipped backfacing from top
  1878. if (use_tri1a2)
  1879. {
  1880. mIndices[i++] = pt1;
  1881. mIndices[i++] = pt2;
  1882. mIndices[i++] = pt1 + 1;
  1883. pt1++;
  1884. }
  1885. else
  1886. {
  1887. mIndices[i++] = pt1;
  1888. mIndices[i++] = pt2;
  1889. mIndices[i++] = pt2 - 1;
  1890. pt2--;
  1891. }
  1892. }
  1893. }
  1894. }
  1895. else
  1896. {
  1897. // Not hollow, generate the triangle fan.
  1898. if (mTypeMask & TOP_MASK)
  1899. {
  1900. if (mTypeMask & OPEN_MASK)
  1901. {
  1902. // SOLID OPEN TOP
  1903. // Generate indices
  1904. // This is a tri-fan, so we reuse the same first point for all triangles.
  1905. for (S32 i = 0; i < (num_vertices - 2); i++)
  1906. {
  1907. mIndices[3*i] = num_vertices - 1;
  1908. mIndices[3*i+1] = i;
  1909. mIndices[3*i+2] = i + 1;
  1910. }
  1911. }
  1912. else
  1913. {
  1914. // SOLID CLOSED TOP
  1915. for (S32 i = 0; i < (num_vertices - 2); i++)
  1916. {
  1917. //MSMSM fix these caps but only for the un-cut case
  1918. mIndices[3*i] = num_vertices - 1;
  1919. mIndices[3*i+1] = i;
  1920. mIndices[3*i+2] = i + 1;
  1921. }
  1922. }
  1923. }
  1924. else
  1925. {
  1926. if (mTypeMask & OPEN_MASK)
  1927. {
  1928. // SOLID OPEN BOTTOM
  1929. // Generate indices
  1930. // This is a tri-fan, so we reuse the same first point for all triangles.
  1931. for (S32 i = 0; i < (num_vertices - 2); i++)
  1932. {
  1933. mIndices[3*i] = num_vertices - 1;
  1934. mIndices[3*i+1] = i + 1;
  1935. mIndices[3*i+2] = i;
  1936. }
  1937. }
  1938. else
  1939. {
  1940. // SOLID CLOSED BOTTOM
  1941. for (S32 i = 0; i < (num_vertices - 2); i++)
  1942. {
  1943. //MSMSM fix these caps but only for the un-cut case
  1944. mIndices[3*i] = num_vertices - 1;
  1945. mIndices[3*i+1] = i + 1;
  1946. mIndices[3*i+2] = i;
  1947. }
  1948. }
  1949. }
  1950. }
  1951. return TRUE;
  1952. }
  1953. void LLVolumeFace::createBinormals()
  1954. {
  1955. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1956. if (!mHasBinormals)
  1957. {
  1958. //generate binormals
  1959. for (U32 i = 0; i < mIndices.size()/3; i++) 
  1960. { //for each triangle
  1961. const VertexData& v0 = mVertices[mIndices[i*3+0]];
  1962. const VertexData& v1 = mVertices[mIndices[i*3+1]];
  1963. const VertexData& v2 = mVertices[mIndices[i*3+2]];
  1964. //calculate binormal
  1965. LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord,
  1966. v1.mPosition, v1.mTexCoord,
  1967. v2.mPosition, v2.mTexCoord);
  1968. for (U32 j = 0; j < 3; j++) 
  1969. { //add triangle normal to vertices
  1970. mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum;
  1971. }
  1972. //even out quad contributions
  1973. if (i % 2 == 0) 
  1974. {
  1975. mVertices[mIndices[i*3+2]].mBinormal += binorm;
  1976. }
  1977. else 
  1978. {
  1979. mVertices[mIndices[i*3+1]].mBinormal += binorm;
  1980. }
  1981. }
  1982. //normalize binormals
  1983. for (U32 i = 0; i < mVertices.size(); i++) 
  1984. {
  1985. mVertices[i].mBinormal.normVec();
  1986. mVertices[i].mNormal.normVec();
  1987. }
  1988. mHasBinormals = TRUE;
  1989. }
  1990. }
  1991. BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
  1992. {
  1993. LLMemType m1(LLMemType::MTYPE_VOLUME);
  1994. BOOL flat = mTypeMask & FLAT_MASK;
  1995. U8 sculpt_type = volume->getParams().getSculptType();
  1996. U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
  1997. BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
  1998. BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
  1999. BOOL sculpt_reverse_horizontal = (sculpt_invert ? !sculpt_mirror : sculpt_mirror);  // XOR
  2000. S32 num_vertices, num_indices;
  2001. const std::vector<LLVolume::Point>& mesh = volume->getMesh();
  2002. const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
  2003. const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath;
  2004. S32 max_s = volume->getProfile().getTotal();
  2005. S32 s, t, i;
  2006. F32 ss, tt;
  2007. num_vertices = mNumS*mNumT;
  2008. num_indices = (mNumS-1)*(mNumT-1)*6;
  2009. mVertices.resize(num_vertices);
  2010. if (!partial_build)
  2011. {
  2012. mIndices.resize(num_indices);
  2013. mEdge.resize(num_indices);
  2014. }
  2015. else
  2016. {
  2017. mHasBinormals = FALSE;
  2018. }
  2019. LLVector3& face_min = mExtents[0];
  2020. LLVector3& face_max = mExtents[1];
  2021. mCenter.clearVec();
  2022. S32 begin_stex = llfloor( profile[mBeginS].mV[2] );
  2023. S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS;
  2024. S32 cur_vertex = 0;
  2025. // Copy the vertices into the array
  2026. for (t = mBeginT; t < mBeginT + mNumT; t++)
  2027. {
  2028. tt = path_data[t].mTexT;
  2029. for (s = 0; s < num_s; s++)
  2030. {
  2031. if (mTypeMask & END_MASK)
  2032. {
  2033. if (s)
  2034. {
  2035. ss = 1.f;
  2036. }
  2037. else
  2038. {
  2039. ss = 0.f;
  2040. }
  2041. }
  2042. else
  2043. {
  2044. // Get s value for tex-coord.
  2045. if (!flat)
  2046. {
  2047. ss = profile[mBeginS + s].mV[2];
  2048. }
  2049. else
  2050. {
  2051. ss = profile[mBeginS + s].mV[2] - begin_stex;
  2052. }
  2053. }
  2054. if (sculpt_reverse_horizontal)
  2055. {
  2056. ss = 1.f - ss;
  2057. }
  2058. // Check to see if this triangle wraps around the array.
  2059. if (mBeginS + s >= max_s)
  2060. {
  2061. // We're wrapping
  2062. i = mBeginS + s + max_s*(t-1);
  2063. }
  2064. else
  2065. {
  2066. i = mBeginS + s + max_s*t;
  2067. }
  2068. mVertices[cur_vertex].mPosition = mesh[i].mPos;
  2069. mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
  2070. mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
  2071. mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
  2072. if (cur_vertex == 0)
  2073. {
  2074. face_min = face_max = mesh[i].mPos;
  2075. }
  2076. else
  2077. {
  2078. update_min_max(face_min, face_max, mesh[i].mPos);
  2079. }
  2080. cur_vertex++;
  2081. if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0)
  2082. {
  2083. mVertices[cur_vertex].mPosition = mesh[i].mPos;
  2084. mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
  2085. mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
  2086. mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
  2087. cur_vertex++;
  2088. }
  2089. }
  2090. if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2)
  2091. {
  2092. if (mTypeMask & OPEN_MASK)
  2093. {
  2094. s = num_s-1;
  2095. }
  2096. else
  2097. {
  2098. s = 0;
  2099. }
  2100. i = mBeginS + s + max_s*t;
  2101. ss = profile[mBeginS + s].mV[2] - begin_stex;
  2102. mVertices[cur_vertex].mPosition = mesh[i].mPos;
  2103. mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt);
  2104. mVertices[cur_vertex].mNormal = LLVector3(0,0,0);
  2105. mVertices[cur_vertex].mBinormal = LLVector3(0,0,0);
  2106. update_min_max(face_min,face_max,mesh[i].mPos);
  2107. cur_vertex++;
  2108. }
  2109. }
  2110. mCenter = (face_min + face_max) * 0.5f;
  2111. S32 cur_index = 0;
  2112. S32 cur_edge = 0;
  2113. BOOL flat_face = mTypeMask & FLAT_MASK;
  2114. if (!partial_build)
  2115. {
  2116. // Now we generate the indices.
  2117. for (t = 0; t < (mNumT-1); t++)
  2118. {
  2119. for (s = 0; s < (mNumS-1); s++)
  2120. {
  2121. mIndices[cur_index++] = s   + mNumS*t; //bottom left
  2122. mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
  2123. mIndices[cur_index++] = s   + mNumS*(t+1); //top left
  2124. mIndices[cur_index++] = s   + mNumS*t; //bottom left
  2125. mIndices[cur_index++] = s+1 + mNumS*t; //bottom right
  2126. mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
  2127. mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face 
  2128. if (t < mNumT-2) { //top right/top left neighbor face 
  2129. mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
  2130. }
  2131. else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor
  2132. mEdge[cur_edge++] = -1;
  2133. }
  2134. else { //wrap on T
  2135. mEdge[cur_edge++] = s*2+1;
  2136. }
  2137. if (s > 0) { //top left/bottom left neighbor face
  2138. mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
  2139. }
  2140. else if (flat_face ||  volume->getProfile().isOpen() == TRUE) { //no neighbor
  2141. mEdge[cur_edge++] = -1;
  2142. }
  2143. else { //wrap on S
  2144. mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1;
  2145. }
  2146. if (t > 0) { //bottom left/bottom right neighbor face
  2147. mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
  2148. }
  2149. else if (mNumT <= 3 || volume->getPath().isOpen() == TRUE) { //no neighbor
  2150. mEdge[cur_edge++] = -1;
  2151. }
  2152. else { //wrap on T
  2153. mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2;
  2154. }
  2155. if (s < mNumS-2) { //bottom right/top right neighbor face
  2156. mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
  2157. }
  2158. else if (flat_face || volume->getProfile().isOpen() == TRUE) { //no neighbor
  2159. mEdge[cur_edge++] = -1;
  2160. }
  2161. else { //wrap on S
  2162. mEdge[cur_edge++] = (mNumS-1)*2*t;
  2163. }
  2164. mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face
  2165. }
  2166. }
  2167. }
  2168. //generate normals 
  2169. for (U32 i = 0; i < mIndices.size()/3; i++) //for each triangle
  2170. {
  2171. const S32 i0 = mIndices[i*3+0];
  2172. const S32 i1 = mIndices[i*3+1];
  2173. const S32 i2 = mIndices[i*3+2];
  2174. const VertexData& v0 = mVertices[i0];
  2175. const VertexData& v1 = mVertices[i1];
  2176. const VertexData& v2 = mVertices[i2];
  2177. //calculate triangle normal
  2178. LLVector3 norm = (v0.mPosition-v1.mPosition) % (v0.mPosition-v2.mPosition);
  2179. for (U32 j = 0; j < 3; j++) 
  2180. { //add triangle normal to vertices
  2181. const S32 idx = mIndices[i*3+j];
  2182. mVertices[idx].mNormal += norm; // * (weight_sum - d[j])/weight_sum;
  2183. }
  2184. //even out quad contributions
  2185. if ((i & 1) == 0) 
  2186. {
  2187. mVertices[i2].mNormal += norm;
  2188. }
  2189. else 
  2190. {
  2191. mVertices[i1].mNormal += norm;
  2192. }
  2193. }
  2194. // adjust normals based on wrapping and stitching
  2195. BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f);
  2196. BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f);
  2197. if (sculpt_stitching == LL_SCULPT_TYPE_NONE)  // logic for non-sculpt volumes
  2198. {
  2199. if (volume->getPath().isOpen() == FALSE)
  2200. { //wrap normals on T
  2201. for (S32 i = 0; i < mNumS; i++)
  2202. {
  2203. LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal;
  2204. mVertices[i].mNormal = norm;
  2205. mVertices[mNumS*(mNumT-1)+i].mNormal = norm;
  2206. }
  2207. }
  2208. if ((volume->getProfile().isOpen() == FALSE) && !(s_bottom_converges))
  2209. { //wrap normals on S
  2210. for (S32 i = 0; i < mNumT; i++)
  2211. {
  2212. LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal;
  2213. mVertices[mNumS * i].mNormal = norm;
  2214. mVertices[mNumS * i+mNumS-1].mNormal = norm;
  2215. }
  2216. }
  2217. if (volume->getPathType() == LL_PCODE_PATH_CIRCLE &&
  2218. ((volume->getProfileType() & LL_PCODE_PROFILE_MASK) == LL_PCODE_PROFILE_CIRCLE_HALF))
  2219. {
  2220. if (s_bottom_converges)
  2221. { //all lower S have same normal
  2222. for (S32 i = 0; i < mNumT; i++)
  2223. {
  2224. mVertices[mNumS*i].mNormal = LLVector3(1,0,0);
  2225. }
  2226. }
  2227. if (s_top_converges)
  2228. { //all upper S have same normal
  2229. for (S32 i = 0; i < mNumT; i++)
  2230. {
  2231. mVertices[mNumS*i+mNumS-1].mNormal = LLVector3(-1,0,0);
  2232. }
  2233. }
  2234. }
  2235. }
  2236. else  // logic for sculpt volumes
  2237. {
  2238. BOOL average_poles = FALSE;
  2239. BOOL wrap_s = FALSE;
  2240. BOOL wrap_t = FALSE;
  2241. if (sculpt_stitching == LL_SCULPT_TYPE_SPHERE)
  2242. average_poles = TRUE;
  2243. if ((sculpt_stitching == LL_SCULPT_TYPE_SPHERE) ||
  2244. (sculpt_stitching == LL_SCULPT_TYPE_TORUS) ||
  2245. (sculpt_stitching == LL_SCULPT_TYPE_CYLINDER))
  2246. wrap_s = TRUE;
  2247. if (sculpt_stitching == LL_SCULPT_TYPE_TORUS)
  2248. wrap_t = TRUE;
  2249. if (average_poles)
  2250. {
  2251. // average normals for north pole
  2252. LLVector3 average(0.0, 0.0, 0.0);
  2253. for (S32 i = 0; i < mNumS; i++)
  2254. {
  2255. average += mVertices[i].mNormal;
  2256. }
  2257. // set average
  2258. for (S32 i = 0; i < mNumS; i++)
  2259. {
  2260. mVertices[i].mNormal = average;
  2261. }
  2262. // average normals for south pole
  2263. average = LLVector3(0.0, 0.0, 0.0);
  2264. for (S32 i = 0; i < mNumS; i++)
  2265. {
  2266. average += mVertices[i + mNumS * (mNumT - 1)].mNormal;
  2267. }
  2268. // set average
  2269. for (S32 i = 0; i < mNumS; i++)
  2270. {
  2271. mVertices[i + mNumS * (mNumT - 1)].mNormal = average;
  2272. }
  2273. }
  2274. if (wrap_s)
  2275. {
  2276. for (S32 i = 0; i < mNumT; i++)
  2277. {
  2278. LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal;
  2279. mVertices[mNumS * i].mNormal = norm;
  2280. mVertices[mNumS * i+mNumS-1].mNormal = norm;
  2281. }
  2282. }
  2283. if (wrap_t)
  2284. {
  2285. for (S32 i = 0; i < mNumS; i++)
  2286. {
  2287. LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal;
  2288. mVertices[i].mNormal = norm;
  2289. mVertices[mNumS*(mNumT-1)+i].mNormal = norm;
  2290. }
  2291. }
  2292. }
  2293. return TRUE;
  2294. }
  2295. // Finds binormal based on three vertices with texture coordinates.
  2296. // Fills in dummy values if the triangle has degenerate texture coordinates.
  2297. LLVector3 calc_binormal_from_triangle( 
  2298. const LLVector3& pos0,
  2299. const LLVector2& tex0,
  2300. const LLVector3& pos1,
  2301. const LLVector2& tex1,
  2302. const LLVector3& pos2,
  2303. const LLVector2& tex2)
  2304. {
  2305. LLVector3 rx0( pos0.mV[VX], tex0.mV[VX], tex0.mV[VY] );
  2306. LLVector3 rx1( pos1.mV[VX], tex1.mV[VX], tex1.mV[VY] );
  2307. LLVector3 rx2( pos2.mV[VX], tex2.mV[VX], tex2.mV[VY] );
  2308. LLVector3 ry0( pos0.mV[VY], tex0.mV[VX], tex0.mV[VY] );
  2309. LLVector3 ry1( pos1.mV[VY], tex1.mV[VX], tex1.mV[VY] );
  2310. LLVector3 ry2( pos2.mV[VY], tex2.mV[VX], tex2.mV[VY] );
  2311. LLVector3 rz0( pos0.mV[VZ], tex0.mV[VX], tex0.mV[VY] );
  2312. LLVector3 rz1( pos1.mV[VZ], tex1.mV[VX], tex1.mV[VY] );
  2313. LLVector3 rz2( pos2.mV[VZ], tex2.mV[VX], tex2.mV[VY] );
  2314. LLVector3 r0 = (rx0 - rx1) % (rx0 - rx2);
  2315. LLVector3 r1 = (ry0 - ry1) % (ry0 - ry2);
  2316. LLVector3 r2 = (rz0 - rz1) % (rz0 - rz2);
  2317. if( r0.mV[VX] && r1.mV[VX] && r2.mV[VX] )
  2318. {
  2319. LLVector3 binormal(
  2320. -r0.mV[VZ] / r0.mV[VX],
  2321. -r1.mV[VZ] / r1.mV[VX],
  2322. -r2.mV[VZ] / r2.mV[VX]);
  2323. // binormal.normVec();
  2324. return binormal;
  2325. }
  2326. else
  2327. {
  2328. return LLVector3( 0, 1 , 0 );
  2329. }
  2330. }