diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llprimitive/llprimitive.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 1768 |
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 | |||
45 | const F32 OBJECT_CUT_MIN = 0.f; | ||
46 | const F32 OBJECT_CUT_MAX = 1.f; | ||
47 | const F32 OBJECT_CUT_INC = 0.05f; | ||
48 | const F32 OBJECT_MIN_CUT_INC = 0.02f; | ||
49 | const F32 OBJECT_ROTATION_PRECISION = 0.05f; | ||
50 | |||
51 | const F32 OBJECT_TWIST_MIN = -360.f; | ||
52 | const F32 OBJECT_TWIST_MAX = 360.f; | ||
53 | const F32 OBJECT_TWIST_INC = 18.f; | ||
54 | |||
55 | // This is used for linear paths, | ||
56 | // since twist is used in a slightly different manner. | ||
57 | const F32 OBJECT_TWIST_LINEAR_MIN = -180.f; | ||
58 | const F32 OBJECT_TWIST_LINEAR_MAX = 180.f; | ||
59 | const F32 OBJECT_TWIST_LINEAR_INC = 9.f; | ||
60 | |||
61 | const F32 OBJECT_MIN_HOLE_SIZE = 0.05f; | ||
62 | const F32 OBJECT_MAX_HOLE_SIZE_X = 1.0f; | ||
63 | const F32 OBJECT_MAX_HOLE_SIZE_Y = 0.5f; | ||
64 | |||
65 | // Revolutions parameters. | ||
66 | const F32 OBJECT_REV_MIN = 1.0f; | ||
67 | const F32 OBJECT_REV_MAX = 4.0f; | ||
68 | const F32 OBJECT_REV_INC = 0.1f; | ||
69 | |||
70 | // lights | ||
71 | const F32 LIGHT_MIN_RADIUS = 0.0f; | ||
72 | const F32 LIGHT_DEFAULT_RADIUS = 5.0f; | ||
73 | const F32 LIGHT_MAX_RADIUS = 20.0f; | ||
74 | const F32 LIGHT_MIN_FALLOFF = 0.0f; | ||
75 | const F32 LIGHT_DEFAULT_FALLOFF = 1.0f; | ||
76 | const F32 LIGHT_MAX_FALLOFF = 2.0f; | ||
77 | const F32 LIGHT_MIN_CUTOFF = 0.0f; | ||
78 | const F32 LIGHT_DEFAULT_CUTOFF = 0.0f; | ||
79 | const F32 LIGHT_MAX_CUTOFF = 180.f; | ||
80 | |||
81 | // "Tension" => [0,10], increments of 0.1 | ||
82 | const F32 FLEXIBLE_OBJECT_MIN_TENSION = 0.0f; | ||
83 | const F32 FLEXIBLE_OBJECT_DEFAULT_TENSION = 1.0f; | ||
84 | const F32 FLEXIBLE_OBJECT_MAX_TENSION = 10.0f; | ||
85 | |||
86 | // "Drag" => [0,10], increments of 0.1 | ||
87 | const F32 FLEXIBLE_OBJECT_MIN_AIR_FRICTION = 0.0f; | ||
88 | const F32 FLEXIBLE_OBJECT_DEFAULT_AIR_FRICTION = 2.0f; | ||
89 | const F32 FLEXIBLE_OBJECT_MAX_AIR_FRICTION = 10.0f; | ||
90 | |||
91 | // "Gravity" = [-10,10], increments of 0.1 | ||
92 | const F32 FLEXIBLE_OBJECT_MIN_GRAVITY = -10.0f; | ||
93 | const F32 FLEXIBLE_OBJECT_DEFAULT_GRAVITY = 0.3f; | ||
94 | const F32 FLEXIBLE_OBJECT_MAX_GRAVITY = 10.0f; | ||
95 | |||
96 | // "Wind" = [0,10], increments of 0.1 | ||
97 | const F32 FLEXIBLE_OBJECT_MIN_WIND_SENSITIVITY = 0.0f; | ||
98 | const F32 FLEXIBLE_OBJECT_DEFAULT_WIND_SENSITIVITY = 0.0f; | ||
99 | const F32 FLEXIBLE_OBJECT_MAX_WIND_SENSITIVITY = 10.0f; | ||
100 | |||
101 | // I'll explain later... | ||
102 | const F32 FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE = 0.99f; | ||
103 | |||
104 | const F32 FLEXIBLE_OBJECT_DEFAULT_LENGTH = 1.0f; | ||
105 | const BOOL FLEXIBLE_OBJECT_DEFAULT_USING_COLLISION_SPHERE = FALSE; | ||
106 | const BOOL FLEXIBLE_OBJECT_DEFAULT_RENDERING_COLLISION_SPHERE = FALSE; | ||
107 | |||
108 | |||
109 | //=============================================================== | ||
110 | LLPrimitive::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 | //=============================================================== | ||
133 | LLPrimitive::~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 | ||
151 | LLPrimitive *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 | //=============================================================== | ||
168 | void 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 | |||
182 | void LLPrimitive::setPCode(const U8 p_code) | ||
183 | { | ||
184 | mPrimitiveCode = p_code; | ||
185 | } | ||
186 | |||
187 | //=============================================================== | ||
188 | const 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 | //=============================================================== | ||
202 | void 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 | //=============================================================== | ||
246 | void 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 | //=============================================================== | ||
257 | void LLPrimitive::setTE(const U8 index, const LLTextureEntry &te) | ||
258 | { | ||
259 | mTextureList[index] = te; | ||
260 | } | ||
261 | |||
262 | S32 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 | |||
274 | S32 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 | |||
286 | S32 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 | |||
298 | S32 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 | //=============================================================== | ||
311 | S32 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 | ||
326 | S32 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 | ||
342 | S32 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 | //=============================================================== | ||
357 | S32 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 | ||
372 | S32 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 | ||
388 | S32 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 | //=============================================================== | ||
403 | S32 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 | //=============================================================== | ||
417 | S32 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 | |||
429 | S32 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 | |||
441 | S32 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 | |||
453 | S32 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 | |||
465 | S32 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 | |||
477 | S32 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 | |||
489 | S32 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 | |||
501 | S32 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 | |||
514 | LLPCode 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 | |||
610 | U8 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. | ||
708 | const 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 | |||
821 | void 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 | |||
845 | S32 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 | |||
858 | BOOL 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 | |||
1112 | BOOL 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 | |||
1125 | void 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 | |||
1169 | const F32 LL_MAX_SCALE_S = 100.0f; | ||
1170 | const F32 LL_MAX_SCALE_T = 100.0f; | ||
1171 | S32 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 | |||
1231 | S32 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 | ||
1276 | BOOL 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 | |||
1352 | BOOL 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 | |||
1428 | S32 LLPrimitive::unpackTEMessage(LLMessageSystem *mesgsys, char *block_name) | ||
1429 | { | ||
1430 | return(unpackTEMessage(mesgsys,block_name,-1)); | ||
1431 | } | ||
1432 | |||
1433 | S32 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 | |||
1529 | S32 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 | |||
1622 | void LLPrimitive::setTextureList(LLTextureEntry *listp) | ||
1623 | { | ||
1624 | LLTextureEntry* old_texture_list = mTextureList; | ||
1625 | mTextureList = listp; | ||
1626 | delete[] old_texture_list; | ||
1627 | } | ||
1628 | |||
1629 | //============================================================================ | ||
1630 | |||
1631 | LLLightParams::LLLightParams() | ||
1632 | { | ||
1633 | mColor.setToWhite(); | ||
1634 | mRadius = 10.f; | ||
1635 | mCutoff = 0.0f; | ||
1636 | mFalloff = 0.75f; | ||
1637 | |||
1638 | mType = PARAMS_LIGHT; | ||
1639 | } | ||
1640 | |||
1641 | BOOL 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 | |||
1651 | BOOL 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 | |||
1662 | bool 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 | |||
1679 | void 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 | |||
1691 | LLFlexibleObjectData::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 | |||
1705 | BOOL 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 | |||
1718 | BOOL 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 | |||
1740 | bool 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 | |||
1757 | void 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 | } | ||