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