/indra/llprimitive/llprimitive.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 1917 lines · 1381 code · 243 blank · 293 comment · 209 complexity · 3929406fa02e4b3fadfe7e2af3d56891 MD5 · raw file

  1. /**
  2. * @file llprimitive.cpp
  3. * @brief LLPrimitive base class
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include "material_codes.h"
  28. #include "llmemtype.h"
  29. #include "llerror.h"
  30. #include "message.h"
  31. #include "llprimitive.h"
  32. #include "llvolume.h"
  33. #include "legacy_object_types.h"
  34. #include "v4coloru.h"
  35. #include "llvolumemgr.h"
  36. #include "llstring.h"
  37. #include "lldatapacker.h"
  38. #include "llsdutil_math.h"
  39. #include "llprimtexturelist.h"
  40. /**
  41. * exported constants
  42. */
  43. const F32 OBJECT_CUT_MIN = 0.f;
  44. const F32 OBJECT_CUT_MAX = 1.f;
  45. const F32 OBJECT_CUT_INC = 0.05f;
  46. const F32 OBJECT_MIN_CUT_INC = 0.02f;
  47. const F32 OBJECT_ROTATION_PRECISION = 0.05f;
  48. const F32 OBJECT_TWIST_MIN = -360.f;
  49. const F32 OBJECT_TWIST_MAX = 360.f;
  50. const F32 OBJECT_TWIST_INC = 18.f;
  51. // This is used for linear paths,
  52. // since twist is used in a slightly different manner.
  53. const F32 OBJECT_TWIST_LINEAR_MIN = -180.f;
  54. const F32 OBJECT_TWIST_LINEAR_MAX = 180.f;
  55. const F32 OBJECT_TWIST_LINEAR_INC = 9.f;
  56. const F32 OBJECT_MIN_HOLE_SIZE = 0.05f;
  57. const F32 OBJECT_MAX_HOLE_SIZE_X = 1.0f;
  58. const F32 OBJECT_MAX_HOLE_SIZE_Y = 0.5f;
  59. // Revolutions parameters.
  60. const F32 OBJECT_REV_MIN = 1.0f;
  61. const F32 OBJECT_REV_MAX = 4.0f;
  62. const F32 OBJECT_REV_INC = 0.1f;
  63. // lights
  64. const F32 LIGHT_MIN_RADIUS = 0.0f;
  65. const F32 LIGHT_DEFAULT_RADIUS = 5.0f;
  66. const F32 LIGHT_MAX_RADIUS = 20.0f;
  67. const F32 LIGHT_MIN_FALLOFF = 0.0f;
  68. const F32 LIGHT_DEFAULT_FALLOFF = 1.0f;
  69. const F32 LIGHT_MAX_FALLOFF = 2.0f;
  70. const F32 LIGHT_MIN_CUTOFF = 0.0f;
  71. const F32 LIGHT_DEFAULT_CUTOFF = 0.0f;
  72. const F32 LIGHT_MAX_CUTOFF = 180.f;
  73. // "Tension" => [0,10], increments of 0.1
  74. const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f;
  75. const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f;
  76. const F32 FLEXIBLE_OBJECT_MAX_TENSION = 10.0f;
  77. // "Drag" => [0,10], increments of 0.1
  78. const F32 FLEXIBLE_OBJECT_MIN_AIR_FRICTION = 0.0f;
  79. const F32 FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION = 2.0f;
  80. const F32 FLEXIBLE_OBJECT_MAX_AIR_FRICTION = 10.0f;
  81. // "Gravity" = [-10,10], increments of 0.1
  82. const F32 FLEXIBLE_OBJECT_MIN_GRAVITY = -10.0f;
  83. const F32 FLEXIBLE_OBJECT_DEFAULT_GRAVITY = 0.3f;
  84. const F32 FLEXIBLE_OBJECT_MAX_GRAVITY = 10.0f;
  85. // "Wind" = [0,10], increments of 0.1
  86. const F32 FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY = 0.0f;
  87. const F32 FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY = 0.0f;
  88. const F32 FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY = 10.0f;
  89. // I'll explain later...
  90. const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE = 0.99f;
  91. const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f;
  92. const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE;
  93. const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE;
  94. const S32 MAX_FACE_BITS = 9;
  95. const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; // old inverted texture: "7595d345-a24c-e7ef-f0bd-78793792133e";
  96. // Texture rotations are sent over the wire as a S16. This is used to scale the actual float
  97. // value to a S16. Don't use 7FFF as it introduces some odd rounding with 180 since it
  98. // can't be divided by 2. See DEV-19108
  99. const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000);
  100. //static
  101. // LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global
  102. // TODO -- eliminate this global from the codebase!
  103. LLVolumeMgr* LLPrimitive::sVolumeManager = NULL;
  104. // static
  105. void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager )
  106. {
  107. if ( !volume_manager || sVolumeManager )
  108. {
  109. llerrs << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << llendl;
  110. }
  111. sVolumeManager = volume_manager;
  112. }
  113. // static
  114. bool LLPrimitive::cleanupVolumeManager()
  115. {
  116. BOOL res = FALSE;
  117. if (sVolumeManager)
  118. {
  119. res = sVolumeManager->cleanup();
  120. delete sVolumeManager;
  121. sVolumeManager = NULL;
  122. }
  123. return res;
  124. }
  125. //===============================================================
  126. LLPrimitive::LLPrimitive()
  127. : mTextureList(),
  128. mNumTEs(0),
  129. mMiscFlags(0)
  130. {
  131. mPrimitiveCode = 0;
  132. mMaterial = LL_MCODE_STONE;
  133. mVolumep = NULL;
  134. mChanged = UNCHANGED;
  135. mPosition.setVec(0.f,0.f,0.f);
  136. mVelocity.setVec(0.f,0.f,0.f);
  137. mAcceleration.setVec(0.f,0.f,0.f);
  138. mRotation.loadIdentity();
  139. mAngularVelocity.setVec(0.f,0.f,0.f);
  140. mScale.setVec(1.f,1.f,1.f);
  141. }
  142. //===============================================================
  143. LLPrimitive::~LLPrimitive()
  144. {
  145. clearTextureList();
  146. // Cleanup handled by volume manager
  147. if (mVolumep)
  148. {
  149. sVolumeManager->unrefVolume(mVolumep);
  150. }
  151. mVolumep = NULL;
  152. }
  153. void LLPrimitive::clearTextureList()
  154. {
  155. }
  156. //===============================================================
  157. // static
  158. LLPrimitive *LLPrimitive::createPrimitive(LLPCode p_code)
  159. {
  160. LLMemType m1(LLMemType::MTYPE_PRIMITIVE);
  161. LLPrimitive *retval = new LLPrimitive();
  162. if (retval)
  163. {
  164. retval->init_primitive(p_code);
  165. }
  166. else
  167. {
  168. llerrs << "primitive allocation failed" << llendl;
  169. }
  170. return retval;
  171. }
  172. //===============================================================
  173. void LLPrimitive::init_primitive(LLPCode p_code)
  174. {
  175. LLMemType m1(LLMemType::MTYPE_PRIMITIVE);
  176. clearTextureList();
  177. mPrimitiveCode = p_code;
  178. }
  179. void LLPrimitive::setPCode(const U8 p_code)
  180. {
  181. mPrimitiveCode = p_code;
  182. }
  183. //===============================================================
  184. LLTextureEntry* LLPrimitive::getTE(const U8 index) const
  185. {
  186. return mTextureList.getTexture(index);
  187. }
  188. //===============================================================
  189. void LLPrimitive::setNumTEs(const U8 num_tes)
  190. {
  191. mTextureList.setSize(num_tes);
  192. }
  193. //===============================================================
  194. void LLPrimitive::setAllTETextures(const LLUUID &tex_id)
  195. {
  196. mTextureList.setAllIDs(tex_id);
  197. }
  198. //===============================================================
  199. void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te)
  200. {
  201. mTextureList.copyTexture(index, te);
  202. }
  203. S32 LLPrimitive::setTETexture(const U8 index, const LLUUID &id)
  204. {
  205. return mTextureList.setID(index, id);
  206. }
  207. S32 LLPrimitive::setTEColor(const U8 index, const LLColor4 &color)
  208. {
  209. return mTextureList.setColor(index, color);
  210. }
  211. S32 LLPrimitive::setTEColor(const U8 index, const LLColor3 &color)
  212. {
  213. return mTextureList.setColor(index, color);
  214. }
  215. S32 LLPrimitive::setTEAlpha(const U8 index, const F32 alpha)
  216. {
  217. return mTextureList.setAlpha(index, alpha);
  218. }
  219. //===============================================================
  220. S32 LLPrimitive::setTEScale(const U8 index, const F32 s, const F32 t)
  221. {
  222. return mTextureList.setScale(index, s, t);
  223. }
  224. // BUG: slow - done this way because texture entries have some
  225. // voodoo related to texture coords
  226. S32 LLPrimitive::setTEScaleS(const U8 index, const F32 s)
  227. {
  228. return mTextureList.setScaleS(index, s);
  229. }
  230. // BUG: slow - done this way because texture entries have some
  231. // voodoo related to texture coords
  232. S32 LLPrimitive::setTEScaleT(const U8 index, const F32 t)
  233. {
  234. return mTextureList.setScaleT(index, t);
  235. }
  236. //===============================================================
  237. S32 LLPrimitive::setTEOffset(const U8 index, const F32 s, const F32 t)
  238. {
  239. return mTextureList.setOffset(index, s, t);
  240. }
  241. // BUG: slow - done this way because texture entries have some
  242. // voodoo related to texture coords
  243. S32 LLPrimitive::setTEOffsetS(const U8 index, const F32 s)
  244. {
  245. return mTextureList.setOffsetS(index, s);
  246. }
  247. // BUG: slow - done this way because texture entries have some
  248. // voodoo related to texture coords
  249. S32 LLPrimitive::setTEOffsetT(const U8 index, const F32 t)
  250. {
  251. return mTextureList.setOffsetT(index, t);
  252. }
  253. //===============================================================
  254. S32 LLPrimitive::setTERotation(const U8 index, const F32 r)
  255. {
  256. return mTextureList.setRotation(index, r);
  257. }
  258. //===============================================================
  259. S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump)
  260. {
  261. return mTextureList.setBumpShinyFullbright(index, bump);
  262. }
  263. S32 LLPrimitive::setTEMediaTexGen(const U8 index, const U8 media)
  264. {
  265. return mTextureList.setMediaTexGen(index, media);
  266. }
  267. S32 LLPrimitive::setTEBumpmap(const U8 index, const U8 bump)
  268. {
  269. return mTextureList.setBumpMap(index, bump);
  270. }
  271. S32 LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny)
  272. {
  273. return mTextureList.setBumpShiny(index, bump_shiny);
  274. }
  275. S32 LLPrimitive::setTETexGen(const U8 index, const U8 texgen)
  276. {
  277. return mTextureList.setTexGen(index, texgen);
  278. }
  279. S32 LLPrimitive::setTEShiny(const U8 index, const U8 shiny)
  280. {
  281. return mTextureList.setShiny(index, shiny);
  282. }
  283. S32 LLPrimitive::setTEFullbright(const U8 index, const U8 fullbright)
  284. {
  285. return mTextureList.setFullbright(index, fullbright);
  286. }
  287. S32 LLPrimitive::setTEMediaFlags(const U8 index, const U8 media_flags)
  288. {
  289. return mTextureList.setMediaFlags(index, media_flags);
  290. }
  291. S32 LLPrimitive::setTEGlow(const U8 index, const F32 glow)
  292. {
  293. return mTextureList.setGlow(index, glow);
  294. }
  295. LLPCode LLPrimitive::legacyToPCode(const U8 legacy)
  296. {
  297. // TODO: Should this default to something valid?
  298. // Maybe volume?
  299. LLPCode pcode = 0;
  300. switch (legacy)
  301. {
  302. /*
  303. case BOX:
  304. pcode = LL_PCODE_CUBE;
  305. break;
  306. case CYLINDER:
  307. pcode = LL_PCODE_CYLINDER;
  308. break;
  309. case CONE:
  310. pcode = LL_PCODE_CONE;
  311. break;
  312. case HALF_CONE:
  313. pcode = LL_PCODE_CONE_HEMI;
  314. break;
  315. case HALF_CYLINDER:
  316. pcode = LL_PCODE_CYLINDER_HEMI;
  317. break;
  318. case HALF_SPHERE:
  319. pcode = LL_PCODE_SPHERE_HEMI;
  320. break;
  321. case PRISM:
  322. pcode = LL_PCODE_PRISM;
  323. break;
  324. case PYRAMID:
  325. pcode = LL_PCODE_PYRAMID;
  326. break;
  327. case SPHERE:
  328. pcode = LL_PCODE_SPHERE;
  329. break;
  330. case TETRAHEDRON:
  331. pcode = LL_PCODE_TETRAHEDRON;
  332. break;
  333. case DEMON:
  334. pcode = LL_PCODE_LEGACY_DEMON;
  335. break;
  336. case LSL_TEST:
  337. pcode = LL_PCODE_LEGACY_LSL_TEST;
  338. break;
  339. case ORACLE:
  340. pcode = LL_PCODE_LEGACY_ORACLE;
  341. break;
  342. case TEXTBUBBLE:
  343. pcode = LL_PCODE_LEGACY_TEXT_BUBBLE;
  344. break;
  345. case ATOR:
  346. pcode = LL_PCODE_LEGACY_ATOR;
  347. break;
  348. case BASIC_SHOT:
  349. pcode = LL_PCODE_LEGACY_SHOT;
  350. break;
  351. case BIG_SHOT:
  352. pcode = LL_PCODE_LEGACY_SHOT_BIG;
  353. break;
  354. case BIRD:
  355. pcode = LL_PCODE_LEGACY_BIRD;
  356. break;
  357. case ROCK:
  358. pcode = LL_PCODE_LEGACY_ROCK;
  359. break;
  360. case SMOKE:
  361. pcode = LL_PCODE_LEGACY_SMOKE;
  362. break;
  363. case SPARK:
  364. pcode = LL_PCODE_LEGACY_SPARK;
  365. break;
  366. */
  367. case PRIMITIVE_VOLUME:
  368. pcode = LL_PCODE_VOLUME;
  369. break;
  370. case GRASS:
  371. pcode = LL_PCODE_LEGACY_GRASS;
  372. break;
  373. case PART_SYS:
  374. pcode = LL_PCODE_LEGACY_PART_SYS;
  375. break;
  376. case PLAYER:
  377. pcode = LL_PCODE_LEGACY_AVATAR;
  378. break;
  379. case TREE:
  380. pcode = LL_PCODE_LEGACY_TREE;
  381. break;
  382. case TREE_NEW:
  383. pcode = LL_PCODE_TREE_NEW;
  384. break;
  385. default:
  386. llwarns << "Unknown legacy code " << legacy << " [" << (S32)legacy << "]!" << llendl;
  387. }
  388. return pcode;
  389. }
  390. U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode)
  391. {
  392. U8 legacy;
  393. switch (pcode)
  394. {
  395. /*
  396. case LL_PCODE_CUBE:
  397. legacy = BOX;
  398. break;
  399. case LL_PCODE_CYLINDER:
  400. legacy = CYLINDER;
  401. break;
  402. case LL_PCODE_CONE:
  403. legacy = CONE;
  404. break;
  405. case LL_PCODE_CONE_HEMI:
  406. legacy = HALF_CONE;
  407. break;
  408. case LL_PCODE_CYLINDER_HEMI:
  409. legacy = HALF_CYLINDER;
  410. break;
  411. case LL_PCODE_SPHERE_HEMI:
  412. legacy = HALF_SPHERE;
  413. break;
  414. case LL_PCODE_PRISM:
  415. legacy = PRISM;
  416. break;
  417. case LL_PCODE_PYRAMID:
  418. legacy = PYRAMID;
  419. break;
  420. case LL_PCODE_SPHERE:
  421. legacy = SPHERE;
  422. break;
  423. case LL_PCODE_TETRAHEDRON:
  424. legacy = TETRAHEDRON;
  425. break;
  426. case LL_PCODE_LEGACY_ATOR:
  427. legacy = ATOR;
  428. break;
  429. case LL_PCODE_LEGACY_SHOT:
  430. legacy = BASIC_SHOT;
  431. break;
  432. case LL_PCODE_LEGACY_SHOT_BIG:
  433. legacy = BIG_SHOT;
  434. break;
  435. case LL_PCODE_LEGACY_BIRD:
  436. legacy = BIRD;
  437. break;
  438. case LL_PCODE_LEGACY_DEMON:
  439. legacy = DEMON;
  440. break;
  441. case LL_PCODE_LEGACY_LSL_TEST:
  442. legacy = LSL_TEST;
  443. break;
  444. case LL_PCODE_LEGACY_ORACLE:
  445. legacy = ORACLE;
  446. break;
  447. case LL_PCODE_LEGACY_ROCK:
  448. legacy = ROCK;
  449. break;
  450. case LL_PCODE_LEGACY_TEXT_BUBBLE:
  451. legacy = TEXTBUBBLE;
  452. break;
  453. case LL_PCODE_LEGACY_SMOKE:
  454. legacy = SMOKE;
  455. break;
  456. case LL_PCODE_LEGACY_SPARK:
  457. legacy = SPARK;
  458. break;
  459. */
  460. case LL_PCODE_VOLUME:
  461. legacy = PRIMITIVE_VOLUME;
  462. break;
  463. case LL_PCODE_LEGACY_GRASS:
  464. legacy = GRASS;
  465. break;
  466. case LL_PCODE_LEGACY_PART_SYS:
  467. legacy = PART_SYS;
  468. break;
  469. case LL_PCODE_LEGACY_AVATAR:
  470. legacy = PLAYER;
  471. break;
  472. case LL_PCODE_LEGACY_TREE:
  473. legacy = TREE;
  474. break;
  475. case LL_PCODE_TREE_NEW:
  476. legacy = TREE_NEW;
  477. break;
  478. default:
  479. llwarns << "Unknown pcode " << (S32)pcode << ":" << pcode << "!" << llendl;
  480. return 0;
  481. }
  482. return legacy;
  483. }
  484. // static
  485. // Don't crash or llerrs here! This function is used for debug strings.
  486. std::string LLPrimitive::pCodeToString(const LLPCode pcode)
  487. {
  488. std::string pcode_string;
  489. U8 base_code = pcode & LL_PCODE_BASE_MASK;
  490. if (!pcode)
  491. {
  492. pcode_string = "null";
  493. }
  494. else if ((base_code) == LL_PCODE_LEGACY)
  495. {
  496. // It's a legacy object
  497. switch (pcode)
  498. {
  499. case LL_PCODE_LEGACY_GRASS:
  500. pcode_string = "grass";
  501. break;
  502. case LL_PCODE_LEGACY_PART_SYS:
  503. pcode_string = "particle system";
  504. break;
  505. case LL_PCODE_LEGACY_AVATAR:
  506. pcode_string = "avatar";
  507. break;
  508. case LL_PCODE_LEGACY_TEXT_BUBBLE:
  509. pcode_string = "text bubble";
  510. break;
  511. case LL_PCODE_LEGACY_TREE:
  512. pcode_string = "tree";
  513. break;
  514. case LL_PCODE_TREE_NEW:
  515. pcode_string = "tree_new";
  516. break;
  517. default:
  518. pcode_string = llformat( "unknown legacy pcode %i",(U32)pcode);
  519. }
  520. }
  521. else
  522. {
  523. std::string shape;
  524. std::string mask;
  525. if (base_code == LL_PCODE_CUBE)
  526. {
  527. shape = "cube";
  528. }
  529. else if (base_code == LL_PCODE_CYLINDER)
  530. {
  531. shape = "cylinder";
  532. }
  533. else if (base_code == LL_PCODE_CONE)
  534. {
  535. shape = "cone";
  536. }
  537. else if (base_code == LL_PCODE_PRISM)
  538. {
  539. shape = "prism";
  540. }
  541. else if (base_code == LL_PCODE_PYRAMID)
  542. {
  543. shape = "pyramid";
  544. }
  545. else if (base_code == LL_PCODE_SPHERE)
  546. {
  547. shape = "sphere";
  548. }
  549. else if (base_code == LL_PCODE_TETRAHEDRON)
  550. {
  551. shape = "tetrahedron";
  552. }
  553. else if (base_code == LL_PCODE_VOLUME)
  554. {
  555. shape = "volume";
  556. }
  557. else if (base_code == LL_PCODE_APP)
  558. {
  559. shape = "app";
  560. }
  561. else
  562. {
  563. llwarns << "Unknown base mask for pcode: " << base_code << llendl;
  564. }
  565. U8 mask_code = pcode & (~LL_PCODE_BASE_MASK);
  566. if (base_code == LL_PCODE_APP)
  567. {
  568. mask = llformat( "%x", mask_code);
  569. }
  570. else if (mask_code & LL_PCODE_HEMI_MASK)
  571. {
  572. mask = "hemi";
  573. }
  574. else
  575. {
  576. mask = llformat( "%x", mask_code);
  577. }
  578. if (mask[0])
  579. {
  580. pcode_string = llformat( "%s-%s", shape.c_str(), mask.c_str());
  581. }
  582. else
  583. {
  584. pcode_string = llformat( "%s", shape.c_str());
  585. }
  586. }
  587. return pcode_string;
  588. }
  589. void LLPrimitive::copyTEs(const LLPrimitive *primitivep)
  590. {
  591. U32 i;
  592. if (primitivep->getExpectedNumTEs() != getExpectedNumTEs())
  593. {
  594. llwarns << "Primitives don't have same expected number of TE's" << llendl;
  595. }
  596. U32 num_tes = llmin(primitivep->getExpectedNumTEs(), getExpectedNumTEs());
  597. if (mTextureList.size() < getExpectedNumTEs())
  598. {
  599. mTextureList.setSize(getExpectedNumTEs());
  600. }
  601. for (i = 0; i < num_tes; i++)
  602. {
  603. mTextureList.copyTexture(i, *(primitivep->getTE(i)));
  604. }
  605. }
  606. S32 face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& faceArray)
  607. {
  608. S32 i;
  609. for (i = 0; i < (S32)faceArray.size(); i++)
  610. {
  611. if (faceArray[i].mFaceID == face_ID)
  612. {
  613. return i;
  614. }
  615. }
  616. return -1;
  617. }
  618. BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
  619. {
  620. LLMemType m1(LLMemType::MTYPE_VOLUME);
  621. LLVolume *volumep;
  622. if (unique_volume)
  623. {
  624. F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail);
  625. if (mVolumep.notNull() && volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail()))
  626. {
  627. return FALSE;
  628. }
  629. volumep = new LLVolume(volume_params, volume_detail, FALSE, TRUE);
  630. }
  631. else
  632. {
  633. if (mVolumep.notNull())
  634. {
  635. F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail);
  636. if (volume_params == mVolumep->getParams() && (volume_detail == mVolumep->getDetail()))
  637. {
  638. return FALSE;
  639. }
  640. }
  641. volumep = sVolumeManager->refVolume(volume_params, detail);
  642. if (volumep == mVolumep)
  643. {
  644. sVolumeManager->unrefVolume( volumep ); // LLVolumeMgr::refVolume() creates a reference, but we don't need a second one.
  645. return TRUE;
  646. }
  647. }
  648. setChanged(GEOMETRY);
  649. if (!mVolumep)
  650. {
  651. mVolumep = volumep;
  652. //mFaceMask = mVolumep->generateFaceMask();
  653. setNumTEs(mVolumep->getNumFaces());
  654. return TRUE;
  655. }
  656. #if 0
  657. // #if 0'd out by davep
  658. // this is a lot of cruft to set texture entry values that just stay the same for LOD switch
  659. // or immediately get overridden by an object update message, also crashes occasionally
  660. U32 old_face_mask = mVolumep->mFaceMask;
  661. S32 face_bit = 0;
  662. S32 cur_mask = 0;
  663. // Grab copies of the old faces from the original shape, ordered by type.
  664. // We will use these to figure out what old texture info gets mapped to new
  665. // faces in the new shape.
  666. std::vector<LLProfile::Face> old_faces;
  667. for (S32 face = 0; face < mVolumep->getNumFaces(); face++)
  668. {
  669. old_faces.push_back(mVolumep->getProfile().mFaces[face]);
  670. }
  671. // Copy the old texture info off to the side, but not in the order in which
  672. // they live in the mTextureList, rather in order of ther "face id" which
  673. // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex.
  674. //
  675. // Hence, some elements of old_tes::mEntryList will be invalid. It is
  676. // initialized to a size of 9 (max number of possible faces on a volume?)
  677. // and only the ones with valid types are filled in.
  678. LLPrimTextureList old_tes;
  679. old_tes.setSize(9);
  680. for (face_bit = 0; face_bit < 9; face_bit++)
  681. {
  682. cur_mask = 0x1 << face_bit;
  683. if (old_face_mask & cur_mask)
  684. {
  685. S32 te_index = face_index_from_id(cur_mask, old_faces);
  686. old_tes.copyTexture(face_bit, *(getTE(te_index)));
  687. //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl;
  688. }
  689. }
  690. // build the new object
  691. sVolumeManager->unrefVolume(mVolumep);
  692. mVolumep = volumep;
  693. U32 new_face_mask = mVolumep->mFaceMask;
  694. S32 i;
  695. if (old_face_mask == new_face_mask)
  696. {
  697. // nothing to do
  698. return TRUE;
  699. }
  700. if (mVolumep->getNumFaces() == 0 && new_face_mask != 0)
  701. {
  702. llwarns << "Object with 0 faces found...INCORRECT!" << llendl;
  703. setNumTEs(mVolumep->getNumFaces());
  704. return TRUE;
  705. }
  706. // initialize face_mapping
  707. S32 face_mapping[9];
  708. for (face_bit = 0; face_bit < 9; face_bit++)
  709. {
  710. face_mapping[face_bit] = face_bit;
  711. }
  712. // The new shape may have more faces than the original, but we can't just
  713. // add them to the end -- the ordering matters and it may be that we must
  714. // insert the new faces in the middle of the list. When we add a face it
  715. // will pick up the texture/color info of one of the old faces an so we
  716. // now figure out which old face info gets mapped to each new face, and
  717. // store in the face_mapping lookup table.
  718. for (face_bit = 0; face_bit < 9; face_bit++)
  719. {
  720. cur_mask = 0x1 << face_bit;
  721. if (!(new_face_mask & cur_mask))
  722. {
  723. // Face doesn't exist in new map.
  724. face_mapping[face_bit] = -1;
  725. continue;
  726. }
  727. else if (old_face_mask & cur_mask)
  728. {
  729. // Face exists in new and old map.
  730. face_mapping[face_bit] = face_bit;
  731. continue;
  732. }
  733. // OK, how we've got a mismatch, where we have to fill a new face with one from
  734. // the old face.
  735. if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE))
  736. {
  737. // It's a top/bottom/hollow interior face.
  738. if (old_face_mask & LL_FACE_PATH_END)
  739. {
  740. face_mapping[face_bit] = 1;
  741. continue;
  742. }
  743. else
  744. {
  745. S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
  746. for (i = 0; i < 4; i++)
  747. {
  748. if (old_face_mask & cur_outer_mask)
  749. {
  750. face_mapping[face_bit] = 5 + i;
  751. break;
  752. }
  753. cur_outer_mask <<= 1;
  754. }
  755. if (i == 4)
  756. {
  757. llwarns << "No path end or outer face in volume!" << llendl;
  758. }
  759. continue;
  760. }
  761. }
  762. if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END))
  763. {
  764. // A cut slice. Use the hollow interior if we have it.
  765. if (old_face_mask & LL_FACE_INNER_SIDE)
  766. {
  767. face_mapping[face_bit] = 2;
  768. continue;
  769. }
  770. // No interior, use the bottom face.
  771. // Could figure out which of the outer faces was nearest, but that would be harder.
  772. if (old_face_mask & LL_FACE_PATH_END)
  773. {
  774. face_mapping[face_bit] = 1;
  775. continue;
  776. }
  777. else
  778. {
  779. S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0;
  780. for (i = 0; i < 4; i++)
  781. {
  782. if (old_face_mask & cur_outer_mask)
  783. {
  784. face_mapping[face_bit] = 5 + i;
  785. break;
  786. }
  787. cur_outer_mask <<= 1;
  788. }
  789. if (i == 4)
  790. {
  791. llwarns << "No path end or outer face in volume!" << llendl;
  792. }
  793. continue;
  794. }
  795. }
  796. // OK, the face that's missing is an outer face...
  797. // Pull from the nearest adjacent outer face (there's always guaranteed to be one...
  798. S32 cur_outer = face_bit - 5;
  799. S32 min_dist = 5;
  800. S32 min_outer_bit = -1;
  801. S32 i;
  802. for (i = 0; i < 4; i++)
  803. {
  804. if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i))
  805. {
  806. S32 dist = abs(i - cur_outer);
  807. if (dist < min_dist)
  808. {
  809. min_dist = dist;
  810. min_outer_bit = i + 5;
  811. }
  812. }
  813. }
  814. if (-1 == min_outer_bit)
  815. {
  816. llinfos << (LLVolume *)mVolumep << llendl;
  817. llwarns << "Bad! No outer faces, impossible!" << llendl;
  818. }
  819. face_mapping[face_bit] = min_outer_bit;
  820. }
  821. setNumTEs(mVolumep->getNumFaces());
  822. for (face_bit = 0; face_bit < 9; face_bit++)
  823. {
  824. // For each possible face type on the new shape we check to see if that
  825. // face exists and if it does we create a texture entry that is a copy
  826. // of one of the originals. Since the originals might not have a
  827. // matching face, we use the face_mapping lookup table to figure out
  828. // which face information to copy.
  829. cur_mask = 0x1 << face_bit;
  830. if (new_face_mask & cur_mask)
  831. {
  832. if (-1 == face_mapping[face_bit])
  833. {
  834. llwarns << "No mapping from old face to new face!" << llendl;
  835. }
  836. S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces);
  837. setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
  838. }
  839. }
  840. #else
  841. // build the new object
  842. sVolumeManager->unrefVolume(mVolumep);
  843. mVolumep = volumep;
  844. setNumTEs(mVolumep->getNumFaces());
  845. #endif
  846. return TRUE;
  847. }
  848. BOOL LLPrimitive::setMaterial(U8 material)
  849. {
  850. if (material != mMaterial)
  851. {
  852. mMaterial = material;
  853. return TRUE;
  854. }
  855. else
  856. {
  857. return FALSE;
  858. }
  859. }
  860. const F32 LL_MAX_SCALE_S = 100.0f;
  861. const F32 LL_MAX_SCALE_T = 100.0f;
  862. S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const
  863. {
  864. S32 face_index;
  865. S32 i;
  866. U64 exception_faces;
  867. U8 *start_loc = cur_ptr;
  868. htonmemcpy(cur_ptr,data_ptr + (last_face_index * data_size), type, data_size);
  869. cur_ptr += data_size;
  870. for (face_index = last_face_index-1; face_index >= 0; face_index--)
  871. {
  872. BOOL already_sent = FALSE;
  873. for (i = face_index+1; i <= last_face_index; i++)
  874. {
  875. if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size))
  876. {
  877. already_sent = TRUE;
  878. break;
  879. }
  880. }
  881. if (!already_sent)
  882. {
  883. exception_faces = 0;
  884. for (i = face_index; i >= 0; i--)
  885. {
  886. if (!memcmp(data_ptr+(data_size *face_index), data_ptr+(data_size *i), data_size))
  887. {
  888. exception_faces |= ((U64)1 << i);
  889. }
  890. }
  891. //assign exception faces to cur_ptr
  892. if (exception_faces >= (0x1 << 7))
  893. {
  894. if (exception_faces >= (0x1 << 14))
  895. {
  896. if (exception_faces >= (0x1 << 21))
  897. {
  898. if (exception_faces >= (0x1 << 28))
  899. {
  900. *cur_ptr++ = (U8)(((exception_faces >> 28) & 0x7F) | 0x80);
  901. }
  902. *cur_ptr++ = (U8)(((exception_faces >> 21) & 0x7F) | 0x80);
  903. }
  904. *cur_ptr++ = (U8)(((exception_faces >> 14) & 0x7F) | 0x80);
  905. }
  906. *cur_ptr++ = (U8)(((exception_faces >> 7) & 0x7F) | 0x80);
  907. }
  908. *cur_ptr++ = (U8)(exception_faces & 0x7F);
  909. htonmemcpy(cur_ptr,data_ptr + (face_index * data_size), type, data_size);
  910. cur_ptr += data_size;
  911. }
  912. }
  913. return (S32)(cur_ptr - start_loc);
  914. }
  915. S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type)
  916. {
  917. U8 *start_loc = cur_ptr;
  918. U64 i;
  919. htonmemcpy(data_ptr,cur_ptr, type,data_size);
  920. cur_ptr += data_size;
  921. for (i = 1; i < face_count; i++)
  922. {
  923. // Already unswizzled, don't need to unswizzle it again!
  924. memcpy(data_ptr+(i*data_size),data_ptr,data_size); /* Flawfinder: ignore */
  925. }
  926. while ((cur_ptr < buffer_end) && (*cur_ptr != 0))
  927. {
  928. // llinfos << "TE exception" << llendl;
  929. i = 0;
  930. while (*cur_ptr & 0x80)
  931. {
  932. i |= ((*cur_ptr++) & 0x7F);
  933. i = i << 7;
  934. }
  935. i |= *cur_ptr++;
  936. for (S32 j = 0; j < face_count; j++)
  937. {
  938. if (i & 0x01)
  939. {
  940. htonmemcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
  941. // char foo[64];
  942. // sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1));
  943. // llinfos << "Assigning " << foo << " to face " << j << llendl;
  944. }
  945. i = i >> 1;
  946. }
  947. cur_ptr += data_size;
  948. }
  949. return (S32)(cur_ptr - start_loc);
  950. }
  951. // Pack information about all texture entries into container:
  952. // { TextureEntry Variable 2 }
  953. // Includes information about image ID, color, scale S,T, offset S,T and rotation
  954. BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
  955. {
  956. const U32 MAX_TES = 32;
  957. U8 image_ids[MAX_TES*16];
  958. U8 colors[MAX_TES*4];
  959. F32 scale_s[MAX_TES];
  960. F32 scale_t[MAX_TES];
  961. S16 offset_s[MAX_TES];
  962. S16 offset_t[MAX_TES];
  963. S16 image_rot[MAX_TES];
  964. U8 bump[MAX_TES];
  965. U8 media_flags[MAX_TES];
  966. U8 glow[MAX_TES];
  967. const U32 MAX_TE_BUFFER = 4096;
  968. U8 packed_buffer[MAX_TE_BUFFER];
  969. U8 *cur_ptr = packed_buffer;
  970. S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1;
  971. if (last_face_index > -1)
  972. {
  973. // ...if we hit the front, send one image id
  974. S8 face_index;
  975. LLColor4U coloru;
  976. for (face_index = 0; face_index <= last_face_index; face_index++)
  977. {
  978. // Directly sending image_ids is not safe!
  979. memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */
  980. // Cast LLColor4 to LLColor4U
  981. coloru.setVec( getTE(face_index)->getColor() );
  982. // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
  983. // as all zeros. However, the subtraction and addition must be done in unsigned
  984. // byte space, not in float space, otherwise off-by-one errors occur. JC
  985. colors[4*face_index] = 255 - coloru.mV[0];
  986. colors[4*face_index + 1] = 255 - coloru.mV[1];
  987. colors[4*face_index + 2] = 255 - coloru.mV[2];
  988. colors[4*face_index + 3] = 255 - coloru.mV[3];
  989. const LLTextureEntry* te = getTE(face_index);
  990. scale_s[face_index] = (F32) te->mScaleS;
  991. scale_t[face_index] = (F32) te->mScaleT;
  992. offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ;
  993. offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ;
  994. image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR));
  995. bump[face_index] = te->getBumpShinyFullbright();
  996. media_flags[face_index] = te->getMediaTexGen();
  997. glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
  998. }
  999. cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
  1000. *cur_ptr++ = 0;
  1001. cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8);
  1002. *cur_ptr++ = 0;
  1003. cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32);
  1004. *cur_ptr++ = 0;
  1005. cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32);
  1006. *cur_ptr++ = 0;
  1007. cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array);
  1008. *cur_ptr++ = 0;
  1009. cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array);
  1010. *cur_ptr++ = 0;
  1011. cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array);
  1012. *cur_ptr++ = 0;
  1013. cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8);
  1014. *cur_ptr++ = 0;
  1015. cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
  1016. *cur_ptr++ = 0;
  1017. cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
  1018. }
  1019. mesgsys->addBinaryDataFast(_PREHASH_TextureEntry, packed_buffer, (S32)(cur_ptr - packed_buffer));
  1020. return FALSE;
  1021. }
  1022. BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
  1023. {
  1024. const U32 MAX_TES = 32;
  1025. U8 image_ids[MAX_TES*16];
  1026. U8 colors[MAX_TES*4];
  1027. F32 scale_s[MAX_TES];
  1028. F32 scale_t[MAX_TES];
  1029. S16 offset_s[MAX_TES];
  1030. S16 offset_t[MAX_TES];
  1031. S16 image_rot[MAX_TES];
  1032. U8 bump[MAX_TES];
  1033. U8 media_flags[MAX_TES];
  1034. U8 glow[MAX_TES];
  1035. const U32 MAX_TE_BUFFER = 4096;
  1036. U8 packed_buffer[MAX_TE_BUFFER];
  1037. U8 *cur_ptr = packed_buffer;
  1038. S32 last_face_index = getNumTEs() - 1;
  1039. if (last_face_index > -1)
  1040. {
  1041. // ...if we hit the front, send one image id
  1042. S8 face_index;
  1043. LLColor4U coloru;
  1044. for (face_index = 0; face_index <= last_face_index; face_index++)
  1045. {
  1046. // Directly sending image_ids is not safe!
  1047. memcpy(&image_ids[face_index*16],getTE(face_index)->getID().mData,16); /* Flawfinder: ignore */
  1048. // Cast LLColor4 to LLColor4U
  1049. coloru.setVec( getTE(face_index)->getColor() );
  1050. // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
  1051. // as all zeros. However, the subtraction and addition must be done in unsigned
  1052. // byte space, not in float space, otherwise off-by-one errors occur. JC
  1053. colors[4*face_index] = 255 - coloru.mV[0];
  1054. colors[4*face_index + 1] = 255 - coloru.mV[1];
  1055. colors[4*face_index + 2] = 255 - coloru.mV[2];
  1056. colors[4*face_index + 3] = 255 - coloru.mV[3];
  1057. const LLTextureEntry* te = getTE(face_index);
  1058. scale_s[face_index] = (F32) te->mScaleS;
  1059. scale_t[face_index] = (F32) te->mScaleT;
  1060. offset_s[face_index] = (S16) llround((llclamp(te->mOffsetS,-1.0f,1.0f) * (F32)0x7FFF)) ;
  1061. offset_t[face_index] = (S16) llround((llclamp(te->mOffsetT,-1.0f,1.0f) * (F32)0x7FFF)) ;
  1062. image_rot[face_index] = (S16) llround(((fmod(te->mRotation, F_TWO_PI)/F_TWO_PI) * TEXTURE_ROTATION_PACK_FACTOR));
  1063. bump[face_index] = te->getBumpShinyFullbright();
  1064. media_flags[face_index] = te->getMediaTexGen();
  1065. glow[face_index] = (U8) llround((llclamp(te->getGlow(), 0.0f, 1.0f) * (F32)0xFF));
  1066. }
  1067. cur_ptr += packTEField(cur_ptr, (U8 *)image_ids, sizeof(LLUUID),last_face_index, MVT_LLUUID);
  1068. *cur_ptr++ = 0;
  1069. cur_ptr += packTEField(cur_ptr, (U8 *)colors, 4 ,last_face_index, MVT_U8);
  1070. *cur_ptr++ = 0;
  1071. cur_ptr += packTEField(cur_ptr, (U8 *)scale_s, 4 ,last_face_index, MVT_F32);
  1072. *cur_ptr++ = 0;
  1073. cur_ptr += packTEField(cur_ptr, (U8 *)scale_t, 4 ,last_face_index, MVT_F32);
  1074. *cur_ptr++ = 0;
  1075. cur_ptr += packTEField(cur_ptr, (U8 *)offset_s, 2 ,last_face_index, MVT_S16Array);
  1076. *cur_ptr++ = 0;
  1077. cur_ptr += packTEField(cur_ptr, (U8 *)offset_t, 2 ,last_face_index, MVT_S16Array);
  1078. *cur_ptr++ = 0;
  1079. cur_ptr += packTEField(cur_ptr, (U8 *)image_rot, 2 ,last_face_index, MVT_S16Array);
  1080. *cur_ptr++ = 0;
  1081. cur_ptr += packTEField(cur_ptr, (U8 *)bump, 1 ,last_face_index, MVT_U8);
  1082. *cur_ptr++ = 0;
  1083. cur_ptr += packTEField(cur_ptr, (U8 *)media_flags, 1 ,last_face_index, MVT_U8);
  1084. *cur_ptr++ = 0;
  1085. cur_ptr += packTEField(cur_ptr, (U8 *)glow, 1 ,last_face_index, MVT_U8);
  1086. }
  1087. dp.packBinaryData(packed_buffer, (S32)(cur_ptr - packed_buffer), "TextureEntry");
  1088. return FALSE;
  1089. }
  1090. S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name)
  1091. {
  1092. return(unpackTEMessage(mesgsys,block_name,-1));
  1093. }
  1094. S32 LLPrimitive::unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num)
  1095. {
  1096. // use a negative block_num to indicate a single-block read (a non-variable block)
  1097. S32 retval = 0;
  1098. const U32 MAX_TES = 32;
  1099. // Avoid construction of 32 UUIDs per call. JC
  1100. U8 image_data[MAX_TES*16];
  1101. U8 colors[MAX_TES*4];
  1102. F32 scale_s[MAX_TES];
  1103. F32 scale_t[MAX_TES];
  1104. S16 offset_s[MAX_TES];
  1105. S16 offset_t[MAX_TES];
  1106. S16 image_rot[MAX_TES];
  1107. U8 bump[MAX_TES];
  1108. U8 media_flags[MAX_TES];
  1109. U8 glow[MAX_TES];
  1110. const U32 MAX_TE_BUFFER = 4096;
  1111. U8 packed_buffer[MAX_TE_BUFFER];
  1112. U8 *cur_ptr = packed_buffer;
  1113. U32 size;
  1114. U32 face_count = 0;
  1115. if (block_num < 0)
  1116. {
  1117. size = mesgsys->getSizeFast(block_name, _PREHASH_TextureEntry);
  1118. }
  1119. else
  1120. {
  1121. size = mesgsys->getSizeFast(block_name, block_num, _PREHASH_TextureEntry);
  1122. }
  1123. if (size == 0)
  1124. {
  1125. return retval;
  1126. }
  1127. if (block_num < 0)
  1128. {
  1129. mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, 0, MAX_TE_BUFFER);
  1130. }
  1131. else
  1132. {
  1133. mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, packed_buffer, 0, block_num, MAX_TE_BUFFER);
  1134. }
  1135. face_count = getNumTEs();
  1136. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
  1137. cur_ptr++;
  1138. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8);
  1139. cur_ptr++;
  1140. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32);
  1141. cur_ptr++;
  1142. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32);
  1143. cur_ptr++;
  1144. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array);
  1145. cur_ptr++;
  1146. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array);
  1147. cur_ptr++;
  1148. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array);
  1149. cur_ptr++;
  1150. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8);
  1151. cur_ptr++;
  1152. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
  1153. cur_ptr++;
  1154. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
  1155. LLColor4 color;
  1156. LLColor4U coloru;
  1157. for (U32 i = 0; i < face_count; i++)
  1158. {
  1159. retval |= setTETexture(i, ((LLUUID*)image_data)[i]);
  1160. retval |= setTEScale(i, scale_s[i], scale_t[i]);
  1161. retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);
  1162. retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
  1163. retval |= setTEBumpShinyFullbright(i, bump[i]);
  1164. retval |= setTEMediaTexGen(i, media_flags[i]);
  1165. retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
  1166. coloru = LLColor4U(colors + 4*i);
  1167. // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
  1168. // as all zeros. However, the subtraction and addition must be done in unsigned
  1169. // byte space, not in float space, otherwise off-by-one errors occur. JC
  1170. color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
  1171. color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
  1172. color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
  1173. color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
  1174. retval |= setTEColor(i, color);
  1175. }
  1176. return retval;
  1177. }
  1178. S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
  1179. {
  1180. // use a negative block_num to indicate a single-block read (a non-variable block)
  1181. S32 retval = 0;
  1182. const U32 MAX_TES = 32;
  1183. // Avoid construction of 32 UUIDs per call
  1184. static LLUUID image_ids[MAX_TES];
  1185. U8 image_data[MAX_TES*16];
  1186. U8 colors[MAX_TES*4];
  1187. F32 scale_s[MAX_TES];
  1188. F32 scale_t[MAX_TES];
  1189. S16 offset_s[MAX_TES];
  1190. S16 offset_t[MAX_TES];
  1191. S16 image_rot[MAX_TES];
  1192. U8 bump[MAX_TES];
  1193. U8 media_flags[MAX_TES];
  1194. U8 glow[MAX_TES];
  1195. const U32 MAX_TE_BUFFER = 4096;
  1196. U8 packed_buffer[MAX_TE_BUFFER];
  1197. U8 *cur_ptr = packed_buffer;
  1198. S32 size;
  1199. U32 face_count = 0;
  1200. if (!dp.unpackBinaryData(packed_buffer, size, "TextureEntry"))
  1201. {
  1202. retval = TEM_INVALID;
  1203. llwarns << "Bad texture entry block! Abort!" << llendl;
  1204. return retval;
  1205. }
  1206. if (size == 0)
  1207. {
  1208. return retval;
  1209. }
  1210. face_count = llmin((U32) getNumTEs(), MAX_TES);
  1211. U32 i;
  1212. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
  1213. cur_ptr++;
  1214. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8);
  1215. cur_ptr++;
  1216. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32);
  1217. cur_ptr++;
  1218. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32);
  1219. cur_ptr++;
  1220. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array);
  1221. cur_ptr++;
  1222. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array);
  1223. cur_ptr++;
  1224. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array);
  1225. cur_ptr++;
  1226. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8);
  1227. cur_ptr++;
  1228. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
  1229. cur_ptr++;
  1230. cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
  1231. for (i = 0; i < face_count; i++)
  1232. {
  1233. memcpy(image_ids[i].mData,&image_data[i*16],16); /* Flawfinder: ignore */
  1234. }
  1235. LLColor4 color;
  1236. LLColor4U coloru;
  1237. for (i = 0; i < face_count; i++)
  1238. {
  1239. retval |= setTETexture(i, image_ids[i]);
  1240. retval |= setTEScale(i, scale_s[i], scale_t[i]);
  1241. retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);
  1242. retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
  1243. retval |= setTEBumpShinyFullbright(i, bump[i]);
  1244. retval |= setTEMediaTexGen(i, media_flags[i]);
  1245. retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
  1246. coloru = LLColor4U(colors + 4*i);
  1247. // Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
  1248. // as all zeros. However, the subtraction and addition must be done in unsigned
  1249. // byte space, not in float space, otherwise off-by-one errors occur. JC
  1250. color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
  1251. color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
  1252. color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
  1253. color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
  1254. retval |= setTEColor(i, color);
  1255. }
  1256. return retval;
  1257. }
  1258. U8 LLPrimitive::getExpectedNumTEs() const
  1259. {
  1260. U8 expected_face_count = 0;
  1261. if (mVolumep)
  1262. {
  1263. expected_face_count = mVolumep->getNumFaces();
  1264. }
  1265. return expected_face_count;
  1266. }
  1267. void LLPrimitive::copyTextureList(const LLPrimTextureList& other_list)
  1268. {
  1269. mTextureList.copy(other_list);
  1270. }
  1271. void LLPrimitive::takeTextureList(LLPrimTextureList& other_list)
  1272. {
  1273. mTextureList.take(other_list);
  1274. }
  1275. //============================================================================
  1276. // Moved from llselectmgr.cpp
  1277. // BUG: Only works for boxes.
  1278. // Face numbering for flex boxes as of 1.14.2
  1279. // static
  1280. bool LLPrimitive::getTESTAxes(const U8 face, U32* s_axis, U32* t_axis)
  1281. {
  1282. if (face == 0)
  1283. {
  1284. *s_axis = VX; *t_axis = VY;
  1285. return true;
  1286. }
  1287. else if (face == 1)
  1288. {
  1289. *s_axis = VX; *t_axis = VZ;
  1290. return true;
  1291. }
  1292. else if (face == 2)
  1293. {
  1294. *s_axis = VY; *t_axis = VZ;
  1295. return true;
  1296. }
  1297. else if (face == 3)
  1298. {
  1299. *s_axis = VX; *t_axis = VZ;
  1300. return true;
  1301. }
  1302. else if (face == 4)
  1303. {
  1304. *s_axis = VY; *t_axis = VZ;
  1305. return true;
  1306. }
  1307. else if (face == 5)
  1308. {
  1309. *s_axis = VX; *t_axis = VY;
  1310. return true;
  1311. }
  1312. else
  1313. {
  1314. // unknown face
  1315. return false;
  1316. }
  1317. }
  1318. //============================================================================
  1319. //static
  1320. BOOL LLNetworkData::isValid(U16 param_type, U32 size)
  1321. {
  1322. // ew - better mechanism needed
  1323. switch(param_type)
  1324. {
  1325. case PARAMS_FLEXIBLE:
  1326. return (size == 16);
  1327. case PARAMS_LIGHT:
  1328. return (size == 16);
  1329. case PARAMS_SCULPT:
  1330. return (size == 17);
  1331. case PARAMS_LIGHT_IMAGE:
  1332. return (size == 28);
  1333. }
  1334. return FALSE;
  1335. }
  1336. //============================================================================
  1337. LLLightParams::LLLightParams()
  1338. {
  1339. mColor.setToWhite();
  1340. mRadius = 10.f;
  1341. mCutoff = 0.0f;
  1342. mFalloff = 0.75f;
  1343. mType = PARAMS_LIGHT;
  1344. }
  1345. BOOL LLLightParams::pack(LLDataPacker &dp) const
  1346. {
  1347. LLColor4U color4u(mColor);
  1348. dp.packColor4U(color4u, "color");
  1349. dp.packF32(mRadius, "radius");
  1350. dp.packF32(mCutoff, "cutoff");
  1351. dp.packF32(mFalloff, "falloff");
  1352. return TRUE;
  1353. }
  1354. BOOL LLLightParams::unpack(LLDataPacker &dp)
  1355. {
  1356. LLColor4U color;
  1357. dp.unpackColor4U(color, "color");
  1358. setColor(LLColor4(color));
  1359. F32 radius;
  1360. dp.unpackF32(radius, "radius");
  1361. setRadius(radius);
  1362. F32 cutoff;
  1363. dp.unpackF32(cutoff, "cutoff");
  1364. setCutoff(cutoff);
  1365. F32 falloff;
  1366. dp.unpackF32(falloff, "falloff");
  1367. setFalloff(falloff);
  1368. return TRUE;
  1369. }
  1370. bool LLLightParams::operator==(const LLNetworkData& data) const
  1371. {
  1372. if (data.mType != PARAMS_LIGHT)
  1373. {
  1374. return false;
  1375. }
  1376. const LLLightParams *param = (const LLLightParams*)&data;
  1377. if (param->mColor != mColor ||
  1378. param->mRadius != mRadius ||
  1379. param->mCutoff != mCutoff ||
  1380. param->mFalloff != mFalloff)
  1381. {
  1382. return false;
  1383. }
  1384. return true;
  1385. }
  1386. void LLLightParams::copy(const LLNetworkData& data)
  1387. {
  1388. const LLLightParams *param = (LLLightParams*)&data;
  1389. mType = param->mType;
  1390. mColor = param->mColor;
  1391. mRadius = param->mRadius;
  1392. mCutoff = param->mCutoff;
  1393. mFalloff = param->mFalloff;
  1394. }
  1395. LLSD LLLightParams::asLLSD() const
  1396. {
  1397. LLSD sd;
  1398. sd["color"] = ll_sd_from_color4(getColor());
  1399. sd["radius"] = getRadius();
  1400. sd["falloff"] = getFalloff();
  1401. sd["cutoff"] = getCutoff();
  1402. return sd;
  1403. }
  1404. bool LLLightParams::fromLLSD(LLSD& sd)
  1405. {
  1406. const char *w;
  1407. w = "color";
  1408. if (sd.has(w))
  1409. {
  1410. setColor( ll_color4_from_sd(sd["color"]) );
  1411. } else goto fail;
  1412. w = "radius";
  1413. if (sd.has(w))
  1414. {
  1415. setRadius( (F32)sd[w].asReal() );
  1416. } else goto fail;
  1417. w = "falloff";
  1418. if (sd.has(w))
  1419. {
  1420. setFalloff( (F32)sd[w].asReal() );
  1421. } else goto fail;
  1422. w = "cutoff";
  1423. if (sd.has(w))
  1424. {
  1425. setCutoff( (F32)sd[w].asReal() );
  1426. } else goto fail;
  1427. return true;
  1428. fail:
  1429. return false;
  1430. }
  1431. //============================================================================
  1432. LLFlexibleObjectData::LLFlexibleObjectData()
  1433. {
  1434. mSimulateLOD = FLEXIBLE_OBJECT_DEFAULT_NUM_SECTIONS;
  1435. mGravity = FLEXIBLE_OBJECT_DEFAULT_GRAVITY;
  1436. mAirFriction = FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION;
  1437. mWindSensitivity = FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY;
  1438. mTension = FLEXIBLE_OBJECT_DEFAULT_TENSION;
  1439. //mUsingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE;
  1440. //mRenderingCollisionSphere = FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE;
  1441. mUserForce = LLVector3(0.f, 0.f, 0.f);
  1442. mType = PARAMS_FLEXIBLE;
  1443. }
  1444. BOOL LLFlexibleObjectData::pack(LLDataPacker &dp) const
  1445. {
  1446. // Custom, uber-svelte pack "softness" in upper bits of tension & drag
  1447. U8 bit1 = (mSimulateLOD & 2) << 6;
  1448. U8 bit2 = (mSimulateLOD & 1) << 7;
  1449. dp.packU8((U8)(mTension*10.01f) + bit1, "tension");
  1450. dp.packU8((U8)(mAirFriction*10.01f) + bit2, "drag");
  1451. dp.packU8((U8)((mGravity+10.f)*10.01f), "gravity");
  1452. dp.packU8((U8)(mWindSensitivity*10.01f), "wind");
  1453. dp.packVector3(mUserForce, "userforce");
  1454. return TRUE;
  1455. }
  1456. BOOL LLFlexibleObjectData::unpack(LLDataPacker &dp)
  1457. {
  1458. U8 tension, friction, gravity, wind;
  1459. U8 bit1, bit2;
  1460. dp.unpackU8(tension, "tension"); bit1 = (tension >> 6) & 2;
  1461. mTension = ((F32)(tension&0x7f))/10.f;
  1462. dp.unpackU8(friction, "drag"); bit2 = (friction >> 7) & 1;
  1463. mAirFriction = ((F32)(friction&0x7f))/10.f;
  1464. mSimulateLOD = bit1 | bit2;
  1465. dp.unpackU8(gravity, "gravity"); mGravity = ((F32)gravity)/10.f - 10.f;
  1466. dp.unpackU8(wind, "wind"); mWindSensitivity = ((F32)wind)/10.f;
  1467. if (dp.hasNext())
  1468. {
  1469. dp.unpackVector3(mUserForce, "userforce");
  1470. }
  1471. else
  1472. {
  1473. mUserForce.setVec(0.f, 0.f, 0.f);
  1474. }
  1475. return TRUE;
  1476. }
  1477. bool LLFlexibleObjectData::operator==(const LLNetworkData& data) const
  1478. {
  1479. if (data.mType != PARAMS_FLEXIBLE)
  1480. {
  1481. return false;
  1482. }
  1483. LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data;
  1484. return (mSimulateLOD == flex_data->mSimulateLOD &&
  1485. mGravity == flex_data->mGravity &&
  1486. mAirFriction == flex_data->mAirFriction &&
  1487. mWindSensitivity == flex_data->mWindSensitivity &&
  1488. mTension == flex_data->mTension &&
  1489. mUserForce == flex_data->mUserForce);
  1490. //mUsingCollisionSphere == flex_data->mUsingCollisionSphere &&
  1491. //mRenderingCollisionSphere == flex_data->mRenderingCollisionSphere
  1492. }
  1493. void LLFlexibleObjectData::copy(const LLNetworkData& data)
  1494. {
  1495. const LLFlexibleObjectData *flex_data = (LLFlexibleObjectData*)&data;
  1496. mSimulateLOD = flex_data->mSimulateLOD;
  1497. mGravity = flex_data->mGravity;
  1498. mAirFriction = flex_data->mAirFriction;
  1499. mWindSensitivity = flex_data->mWindSensitivity;
  1500. mTension = flex_data->mTension;
  1501. mUserForce = flex_data->mUserForce;
  1502. //mUsingCollisionSphere = flex_data->mUsingCollisionSphere;
  1503. //mRenderingCollisionSphere = flex_data->mRenderingCollisionSphere;
  1504. }
  1505. LLSD LLFlexibleObjectData::asLLSD() const
  1506. {
  1507. LLSD sd;
  1508. sd["air_friction"] = getAirFriction();
  1509. sd["gravity"] = getGravity();
  1510. sd["simulate_lod"] = getSimulateLOD();
  1511. sd["tension"] = getTension();
  1512. sd["user_force"] = getUserForce().getValue();
  1513. sd["wind_sensitivity"] = getWindSensitivity();
  1514. return sd;
  1515. }
  1516. bool LLFlexibleObjectData::fromLLSD(LLSD& sd)
  1517. {
  1518. const char *w;
  1519. w = "air_friction";
  1520. if (sd.has(w))
  1521. {
  1522. setAirFriction( (F32)sd[w].asReal() );
  1523. } else goto fail;
  1524. w = "gravity";
  1525. if (sd.has(w))
  1526. {
  1527. setGravity( (F32)sd[w].asReal() );
  1528. } else goto fail;
  1529. w = "simulate_lod";
  1530. if (sd.has(w))
  1531. {
  1532. setSimulateLOD( sd[w].asInteger() );
  1533. } else goto fail;
  1534. w = "tension";
  1535. if (sd.has(w))
  1536. {
  1537. setTension( (F32)sd[w].asReal() );
  1538. } else goto fail;
  1539. w = "user_force";
  1540. if (sd.has(w))
  1541. {
  1542. LLVector3 user_force = ll_vector3_from_sd(sd[w], 0);
  1543. setUserForce( user_force );
  1544. } else goto fail;
  1545. w = "wind_sensitivity";
  1546. if (sd.has(w))
  1547. {
  1548. setWindSensitivity( (F32)sd[w].asReal() );
  1549. } else goto fail;
  1550. return true;
  1551. fail:
  1552. return false;
  1553. }
  1554. //============================================================================
  1555. LLSculptParams::LLSculptParams()
  1556. {
  1557. mType = PARAMS_SCULPT;
  1558. mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
  1559. mSculptType = LL_SCULPT_TYPE_SPHERE;
  1560. }
  1561. BOOL LLSculptParams::pack(LLDataPacker &dp) const
  1562. {
  1563. dp.packUUID(mSculptTexture, "texture");
  1564. dp.packU8(mSculptType, "type");
  1565. return TRUE;
  1566. }
  1567. BOOL LLSculptParams::unpack(LLDataPacker &dp)
  1568. {
  1569. dp.unpackUUID(mSculptTexture, "texture");
  1570. dp.unpackU8(mSculptType, "type");
  1571. return TRUE;
  1572. }
  1573. bool LLSculptParams::operator==(const LLNetworkData& data) const
  1574. {
  1575. if (data.mType != PARAMS_SCULPT)
  1576. {
  1577. return false;
  1578. }
  1579. const LLSculptParams *param = (const LLSculptParams*)&data;
  1580. if ( (param->mSculptTexture != mSculptTexture) ||
  1581. (param->mSculptType != mSculptType) )
  1582. {
  1583. return false;
  1584. }
  1585. return true;
  1586. }
  1587. void LLSculptParams::copy(const LLNetworkData& data)
  1588. {
  1589. const LLSculptParams *param = (LLSculptParams*)&data;
  1590. mSculptTexture = param->mSculptTexture;
  1591. mSculptType = param->mSculptType;
  1592. }
  1593. LLSD LLSculptParams::asLLSD() const
  1594. {
  1595. LLSD sd;
  1596. sd["texture"] = mSculptTexture;
  1597. sd["type"] = mSculptType;
  1598. return sd;
  1599. }
  1600. bool LLSculptParams::fromLLSD(LLSD& sd)
  1601. {
  1602. const char *w;
  1603. w = "texture";
  1604. if (sd.has(w))
  1605. {
  1606. setSculptTexture( sd[w] );
  1607. } else goto fail;
  1608. w = "type";
  1609. if (sd.has(w))
  1610. {
  1611. setSculptType( (U8)sd[w].asInteger() );
  1612. } else goto fail;
  1613. return true;
  1614. fail:
  1615. return false;
  1616. }
  1617. //============================================================================
  1618. LLLightImageParams::LLLightImageParams()
  1619. {
  1620. mType = PARAMS_LIGHT_IMAGE;
  1621. mParams.setVec(F_PI*0.5f, 0.f, 0.f);
  1622. }
  1623. BOOL LLLightImageParams::pack(LLDataPacker &dp) const
  1624. {
  1625. dp.packUUID(mLightTexture, "texture");
  1626. dp.packVector3(mParams, "params");
  1627. return TRUE;
  1628. }
  1629. BOOL LLLightImageParams::unpack(LLDataPacker &dp)
  1630. {
  1631. dp.unpackUUID(mLightTexture, "texture");
  1632. dp.unpackVector3(mParams, "params");
  1633. return TRUE;
  1634. }
  1635. bool LLLightImageParams::operator==(const LLNetworkData& data) const
  1636. {
  1637. if (data.mType != PARAMS_LIGHT_IMAGE)
  1638. {
  1639. return false;
  1640. }
  1641. const LLLightImageParams *param = (const LLLightImageParams*)&data;
  1642. if ( (param->mLightTexture != mLightTexture) )
  1643. {
  1644. return false;
  1645. }
  1646. if ( (param->mParams != mParams ) )
  1647. {
  1648. return false;
  1649. }
  1650. return true;
  1651. }
  1652. void LLLightImageParams::copy(const LLNetworkData& data)
  1653. {
  1654. const LLLightImageParams *param = (LLLightImageParams*)&data;
  1655. mLightTexture = param->mLightTexture;
  1656. mParams = param->mParams;
  1657. }
  1658. LLSD LLLightImageParams::asLLSD() const
  1659. {
  1660. LLSD sd;
  1661. sd["texture"] = mLightTexture;
  1662. sd["params"] = mParams.getValue();
  1663. return sd;
  1664. }
  1665. bool LLLightImageParams::fromLLSD(LLSD& sd)
  1666. {
  1667. if (sd.has("texture"))
  1668. {
  1669. setLightTexture( sd["texture"] );
  1670. setParams( LLVector3( sd["params"] ) );
  1671. return true;
  1672. }
  1673. return false;
  1674. }