PageRenderTime 144ms CodeModel.GetById 31ms app.highlight 80ms RepoModel.GetById 20ms app.codeStats 0ms

/indra/llprimitive/llvolumemessage.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 555 lines | 384 code | 105 blank | 66 comment | 13 complexity | cb335c8ff6f1b63e41504e7ab0b56955 MD5 | raw file
  1/** 
  2 * @file llvolumemessage.cpp
  3 * @brief LLVolumeMessage base class
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "message.h"
 30#include "llvolumemessage.h"
 31#include "lldatapacker.h"
 32
 33//============================================================================
 34
 35// LLVolumeMessage is just a wrapper class; all members are static
 36
 37//============================================================================
 38
 39bool LLVolumeMessage::packProfileParams(
 40	const LLProfileParams* params,
 41	LLMessageSystem *mesgsys)
 42{
 43	// Default to cylinder
 44	static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U16(0), U16(0), U16(0));
 45	
 46	if (!params)
 47		params = &defaultparams;
 48	
 49	U8 tempU8;
 50	U16 tempU16;
 51	
 52	tempU8 = params->getCurveType();
 53	mesgsys->addU8Fast(_PREHASH_ProfileCurve, tempU8);
 54
 55	tempU16 = (U16) llround( params->getBegin() / CUT_QUANTA);
 56	mesgsys->addU16Fast(_PREHASH_ProfileBegin, tempU16);
 57
 58	tempU16 = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA);
 59	mesgsys->addU16Fast(_PREHASH_ProfileEnd, tempU16);
 60
 61	tempU16 = (U16) llround(params->getHollow() / HOLLOW_QUANTA);
 62	mesgsys->addU16Fast(_PREHASH_ProfileHollow, tempU16);
 63
 64	return true;
 65}
 66
 67bool LLVolumeMessage::packProfileParams(
 68	const LLProfileParams* params,
 69	LLDataPacker &dp)
 70{
 71	// Default to cylinder
 72	static LLProfileParams defaultparams(LL_PCODE_PROFILE_CIRCLE, U16(0), U16(0), U16(0));
 73	
 74	if (!params)
 75		params = &defaultparams;
 76	
 77	U8 tempU8;
 78	U16 tempU16;
 79	
 80	tempU8 = params->getCurveType();
 81	dp.packU8(tempU8, "Curve");
 82
 83	tempU16 = (U16) llround( params->getBegin() / CUT_QUANTA);
 84	dp.packU16(tempU16, "Begin");
 85
 86	tempU16 = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA);
 87	dp.packU16(tempU16, "End");
 88
 89	tempU16 = (U16) llround(params->getHollow() / HOLLOW_QUANTA);
 90	dp.packU16(tempU16, "Hollow");
 91	return true;
 92}
 93
 94bool LLVolumeMessage::unpackProfileParams(
 95	LLProfileParams* params,
 96	LLMessageSystem* mesgsys,
 97	char const* block_name,
 98	S32 block_num)
 99{
100	bool ok = true;
101	U8 temp_u8;
102	U16 temp_u16;
103	F32 temp_f32;
104
105	mesgsys->getU8Fast(block_name, _PREHASH_ProfileCurve, temp_u8, block_num);
106	params->setCurveType(temp_u8);
107
108	mesgsys->getU16Fast(block_name, _PREHASH_ProfileBegin, temp_u16, block_num);
109	temp_f32 = temp_u16 * CUT_QUANTA;
110	if (temp_f32 > 1.f)
111	{
112		llwarns << "Profile begin out of range: " << temp_f32
113			<< ". Clamping to 0.0." << llendl;
114		temp_f32 = 0.f;
115		ok = false;
116	}
117	params->setBegin(temp_f32);
118
119	mesgsys->getU16Fast(block_name, _PREHASH_ProfileEnd, temp_u16, block_num);
120	temp_f32 = temp_u16 * CUT_QUANTA;
121	if (temp_f32 > 1.f)
122	{
123		llwarns << "Profile end out of range: " << 1.f - temp_f32
124			<< ". Clamping to 1.0." << llendl;
125		temp_f32 = 1.f;
126		ok = false;
127	}
128	params->setEnd(1.f - temp_f32);
129
130	mesgsys->getU16Fast(block_name, _PREHASH_ProfileHollow, temp_u16, block_num);
131	temp_f32 = temp_u16 * HOLLOW_QUANTA;
132	if (temp_f32 > 1.f)
133	{
134		llwarns << "Profile hollow out of range: " << temp_f32
135			<< ". Clamping to 0.0." << llendl;
136		temp_f32 = 0.f;
137		ok = false;
138	}
139	params->setHollow(temp_f32);
140
141	/*
142	llinfos << "Unpacking Profile Block " << block_num << llendl;
143	llinfos << "Curve:     " << (U32)getCurve() << llendl;
144	llinfos << "Begin:     " << getBegin() << llendl;
145	llinfos << "End:     " << getEnd() << llendl;
146	llinfos << "Hollow:     " << getHollow() << llendl;
147	*/
148	return ok;
149
150}
151
152bool LLVolumeMessage::unpackProfileParams(
153	LLProfileParams* params,
154	LLDataPacker &dp)
155{
156	bool ok = true;
157	U8 temp_u8;
158	U16 temp_u16;
159	F32 temp_f32;
160
161	dp.unpackU8(temp_u8, "Curve");
162	params->setCurveType(temp_u8);
163
164	dp.unpackU16(temp_u16, "Begin");
165	temp_f32 = temp_u16 * CUT_QUANTA;
166	if (temp_f32 > 1.f)
167	{
168		llwarns << "Profile begin out of range: " << temp_f32 << llendl;
169		llwarns << "Clamping to 0.0" << llendl;
170		temp_f32 = 0.f;
171		ok = false;
172	}
173	params->setBegin(temp_f32);
174
175	dp.unpackU16(temp_u16, "End");
176	temp_f32 = temp_u16 * CUT_QUANTA;
177	if (temp_f32 > 1.f)
178	{
179		llwarns << "Profile end out of range: " << 1.f - temp_f32 << llendl;
180		llwarns << "Clamping to 1.0" << llendl;
181		temp_f32 = 1.f;
182		ok = false;
183	}
184	params->setEnd(1.f - temp_f32);
185
186	dp.unpackU16(temp_u16, "Hollow");
187	temp_f32 = temp_u16 * HOLLOW_QUANTA;
188	if (temp_f32 > 1.f)
189	{
190		llwarns << "Profile hollow out of range: " << temp_f32 << llendl;
191		llwarns << "Clamping to 0.0" << llendl;
192		temp_f32 = 0.f;
193		ok = false;
194	}
195	params->setHollow(temp_f32);
196
197	return ok;
198}
199
200//============================================================================
201
202// Quantization:
203// For cut begin, range is 0 to 1, quanta is 0.005, 0 maps to 0
204// For cut end, range is 0 to 1, quanta is 0.005, 1 maps to 0
205// For scale, range is 0 to 1, quanta is 0.01, 0 maps to 0, 1 maps to 100
206// For shear, range is -0.5 to 0.5, quanta is 0.01, 0 maps to 0
207// For taper, range is -1 to 1, quanta is 0.01, 0 maps to 0
208bool LLVolumeMessage::packPathParams(
209	const LLPathParams* params,
210	LLMessageSystem *mesgsys)
211{
212	// Default to cylinder with no cut, top same size as bottom, no shear, no twist
213	static LLPathParams defaultparams(LL_PCODE_PATH_LINE, U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), 0);
214	if (!params)
215		params = &defaultparams;
216	
217	U8 curve = params->getCurveType();
218	mesgsys->addU8Fast(_PREHASH_PathCurve, curve);
219
220	U16 begin = (U16) llround(params->getBegin() / CUT_QUANTA);
221	mesgsys->addU16Fast(_PREHASH_PathBegin, begin);
222
223	U16 end = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA);
224	mesgsys->addU16Fast(_PREHASH_PathEnd, end);
225
226	// Avoid truncation problem with direct F32->U8 cast.
227	// (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50.
228
229	U8 pack_scale_x = 200 - (U8) llround(params->getScaleX() / SCALE_QUANTA);
230	mesgsys->addU8Fast(_PREHASH_PathScaleX, pack_scale_x );
231
232	U8 pack_scale_y = 200 - (U8) llround(params->getScaleY() / SCALE_QUANTA);
233	mesgsys->addU8Fast(_PREHASH_PathScaleY, pack_scale_y );
234
235	U8 pack_shear_x = (U8) llround(params->getShearX() / SHEAR_QUANTA);
236	mesgsys->addU8Fast(_PREHASH_PathShearX, pack_shear_x );
237
238	U8 pack_shear_y = (U8) llround(params->getShearY() / SHEAR_QUANTA);
239	mesgsys->addU8Fast(_PREHASH_PathShearY, pack_shear_y );
240
241	S8 twist = (S8) llround(params->getTwist() / SCALE_QUANTA);
242	mesgsys->addS8Fast(_PREHASH_PathTwist, twist);
243
244	S8 twist_begin = (S8) llround(params->getTwistBegin() / SCALE_QUANTA);
245	mesgsys->addS8Fast(_PREHASH_PathTwistBegin, twist_begin);
246
247	S8 radius_offset = (S8) llround(params->getRadiusOffset() / SCALE_QUANTA);
248	mesgsys->addS8Fast(_PREHASH_PathRadiusOffset, radius_offset);
249
250	S8 taper_x = (S8) llround(params->getTaperX() / TAPER_QUANTA);
251	mesgsys->addS8Fast(_PREHASH_PathTaperX, taper_x);
252
253	S8 taper_y = (S8) llround(params->getTaperY() / TAPER_QUANTA);
254	mesgsys->addS8Fast(_PREHASH_PathTaperY, taper_y);
255
256	U8 revolutions = (U8) llround( (params->getRevolutions() - 1.0f) / REV_QUANTA);
257	mesgsys->addU8Fast(_PREHASH_PathRevolutions, revolutions);
258
259	S8 skew = (S8) llround(params->getSkew() / SCALE_QUANTA);
260	mesgsys->addS8Fast(_PREHASH_PathSkew, skew);
261
262	return true;
263}
264
265bool LLVolumeMessage::packPathParams(
266	const LLPathParams* params,
267	LLDataPacker &dp)
268{
269	// Default to cylinder with no cut, top same size as bottom, no shear, no twist
270	static LLPathParams defaultparams(LL_PCODE_PATH_LINE, U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), U8(0), 0);
271	if (!params)
272		params = &defaultparams;
273	
274	U8 curve = params->getCurveType();
275	dp.packU8(curve, "Curve");
276
277	U16 begin = (U16) llround(params->getBegin() / CUT_QUANTA);
278	dp.packU16(begin, "Begin");
279
280	U16 end = 50000 - (U16) llround(params->getEnd() / CUT_QUANTA);
281	dp.packU16(end, "End");
282
283	// Avoid truncation problem with direct F32->U8 cast.
284	// (e.g., (U8) (0.50 / 0.01) = (U8) 49.9999999 = 49 not 50.
285
286	U8 pack_scale_x = 200 - (U8) llround(params->getScaleX() / SCALE_QUANTA);
287	dp.packU8(pack_scale_x, "ScaleX");
288
289	U8 pack_scale_y = 200 - (U8) llround(params->getScaleY() / SCALE_QUANTA);
290	dp.packU8(pack_scale_y, "ScaleY");
291
292	S8 pack_shear_x = (S8) llround(params->getShearX() / SHEAR_QUANTA);
293	dp.packU8(*(U8 *)&pack_shear_x, "ShearX");
294
295	S8 pack_shear_y = (S8) llround(params->getShearY() / SHEAR_QUANTA);
296	dp.packU8(*(U8 *)&pack_shear_y, "ShearY");
297
298	S8 twist = (S8) llround(params->getTwist() / SCALE_QUANTA);
299	dp.packU8(*(U8 *)&twist, "Twist");
300	
301	S8 twist_begin = (S8) llround(params->getTwistBegin() / SCALE_QUANTA);
302	dp.packU8(*(U8 *)&twist_begin, "TwistBegin");
303
304	S8 radius_offset = (S8) llround(params->getRadiusOffset() / SCALE_QUANTA);
305	dp.packU8(*(U8 *)&radius_offset, "RadiusOffset");
306
307	S8 taper_x = (S8) llround(params->getTaperX() / TAPER_QUANTA);
308	dp.packU8(*(U8 *)&taper_x, "TaperX");
309
310	S8 taper_y = (S8) llround(params->getTaperY() / TAPER_QUANTA);
311	dp.packU8(*(U8 *)&taper_y, "TaperY");
312
313	U8 revolutions = (U8) llround( (params->getRevolutions() - 1.0f) / REV_QUANTA);
314	dp.packU8(*(U8 *)&revolutions, "Revolutions");
315
316	S8 skew = (S8) llround(params->getSkew() / SCALE_QUANTA);
317	dp.packU8(*(U8 *)&skew, "Skew");
318
319	return true;
320}
321
322bool LLVolumeMessage::unpackPathParams(
323	LLPathParams* params,
324	LLMessageSystem* mesgsys,
325	char const* block_name,
326	S32 block_num)
327{
328	U8 curve;
329	mesgsys->getU8Fast(block_name, _PREHASH_PathCurve, curve, block_num);
330	params->setCurveType(curve);
331
332	U16 begin;
333	mesgsys->getU16Fast(block_name, _PREHASH_PathBegin, begin, block_num);
334	params->setBegin((F32)(begin * CUT_QUANTA));
335
336	U16 end;
337	mesgsys->getU16Fast(block_name, _PREHASH_PathEnd, end, block_num);
338	params->setEnd((F32)((50000 - end) * CUT_QUANTA));
339
340	U8 pack_scale_x, pack_scale_y;
341	mesgsys->getU8Fast(block_name, _PREHASH_PathScaleX, pack_scale_x, block_num);
342	mesgsys->getU8Fast(block_name, _PREHASH_PathScaleY, pack_scale_y, block_num);
343	F32 x = (F32) (200 - pack_scale_x) * SCALE_QUANTA;
344	F32 y = (F32) (200 - pack_scale_y) * SCALE_QUANTA;
345	params->setScale( x, y );
346
347	S8 shear_x_quant, shear_y_quant;
348	mesgsys->getS8Fast(block_name, _PREHASH_PathShearX, shear_x_quant, block_num);
349	mesgsys->getS8Fast(block_name, _PREHASH_PathShearY, shear_y_quant, block_num);
350	F32 shear_x = (F32) shear_x_quant * SHEAR_QUANTA;
351	F32 shear_y = (F32) shear_y_quant * SHEAR_QUANTA;
352	params->setShear( shear_x, shear_y );
353
354	S8 twist;
355	mesgsys->getS8Fast(block_name, _PREHASH_PathTwist, twist, block_num );
356	params->setTwist((F32)(twist * SCALE_QUANTA));
357
358	S8 twist_begin;
359	mesgsys->getS8Fast(block_name, _PREHASH_PathTwistBegin, twist_begin, block_num );
360	params->setTwistBegin((F32)(twist_begin * SCALE_QUANTA));
361	
362	S8 radius_offset;
363	mesgsys->getS8Fast(block_name, _PREHASH_PathRadiusOffset, radius_offset, block_num );
364	params->setRadiusOffset((F32)(radius_offset * SCALE_QUANTA));
365
366	S8 taper_x_quant, taper_y_quant;
367	mesgsys->getS8Fast(block_name, _PREHASH_PathTaperX, taper_x_quant, block_num );
368	mesgsys->getS8Fast(block_name, _PREHASH_PathTaperY, taper_y_quant, block_num );
369	F32 taper_x = (F32)(taper_x_quant * TAPER_QUANTA);
370	F32 taper_y = (F32)(taper_y_quant * TAPER_QUANTA);
371	params->setTaper( taper_x, taper_y );
372
373	U8 revolutions;
374	mesgsys->getU8Fast(block_name, _PREHASH_PathRevolutions, revolutions, block_num );
375	params->setRevolutions((F32)(revolutions * REV_QUANTA + 1.0f));
376
377	S8 skew;
378	mesgsys->getS8Fast(block_name, _PREHASH_PathSkew, skew, block_num );
379	params->setSkew((F32)(skew * SCALE_QUANTA));
380
381/*
382	llinfos << "Unpacking Path Block " << block_num << llendl;
383	llinfos << "Curve:     " << (U32)params->getCurve() << llendl;
384	llinfos << "Begin:     " << params->getBegin() << llendl;
385	llinfos << "End:     " << params->getEnd() << llendl;
386	llinfos << "Scale:     " << params->getScale() << llendl;
387	llinfos << "Twist:     " << params->getTwist() << llendl;
388*/
389
390	return true;
391
392}
393
394bool LLVolumeMessage::unpackPathParams(LLPathParams* params, LLDataPacker &dp)
395{
396	U8 value;
397	S8 svalue;
398	U16 temp_u16;
399	
400	dp.unpackU8(value, "Curve");
401	params->setCurveType( value );
402
403	dp.unpackU16(temp_u16, "Begin");
404	params->setBegin((F32)(temp_u16 * CUT_QUANTA));
405
406	dp.unpackU16(temp_u16, "End");
407	params->setEnd((F32)((50000 - temp_u16) * CUT_QUANTA));
408
409	dp.unpackU8(value, "ScaleX");
410	F32 x = (F32) (200 - value) * SCALE_QUANTA;
411	dp.unpackU8(value, "ScaleY");
412	F32 y = (F32) (200 - value) * SCALE_QUANTA;
413	params->setScale( x, y );
414
415	dp.unpackU8(value, "ShearX");
416	svalue = *(S8 *)&value;
417	F32 shear_x = (F32) svalue * SHEAR_QUANTA;
418	dp.unpackU8(value, "ShearY");
419	svalue = *(S8 *)&value;
420	F32 shear_y = (F32) svalue * SHEAR_QUANTA;
421	params->setShear( shear_x, shear_y );
422
423	dp.unpackU8(value, "Twist");
424	svalue = *(S8 *)&value;
425	params->setTwist((F32)(svalue * SCALE_QUANTA));
426
427	dp.unpackU8(value, "TwistBegin");
428	svalue = *(S8 *)&value;
429	params->setTwistBegin((F32)(svalue * SCALE_QUANTA));
430
431	dp.unpackU8(value, "RadiusOffset");
432	svalue = *(S8 *)&value;
433	params->setRadiusOffset((F32)(svalue * SCALE_QUANTA));
434
435	dp.unpackU8(value, "TaperX");
436	svalue = *(S8 *)&value;
437	params->setTaperX((F32)(svalue * TAPER_QUANTA));
438
439	dp.unpackU8(value, "TaperY");
440	svalue = *(S8 *)&value;
441	params->setTaperY((F32)(svalue * TAPER_QUANTA));
442
443	dp.unpackU8(value, "Revolutions");
444	params->setRevolutions((F32)(value * REV_QUANTA + 1.0f));
445
446	dp.unpackU8(value, "Skew");
447	svalue = *(S8 *)&value;
448	params->setSkew((F32)(svalue * SCALE_QUANTA));
449
450	return true;
451}
452
453//============================================================================
454
455// static
456bool LLVolumeMessage::constrainVolumeParams(LLVolumeParams& params)
457{
458	U32 bad = 0;
459
460	// This is called immediately after an unpack. feed the raw data
461	// through the checked setters to constraint it to a valid set of
462	// volume params.
463	bad |= params.setType(params.getProfileParams().getCurveType(),
464						 params.getPathParams().getCurveType()) ? 0 : 1;
465	bad |= params.setBeginAndEndS(params.getProfileParams().getBegin(),
466								  params.getProfileParams().getEnd()) ? 0 : 2;
467	bad |= params.setBeginAndEndT(params.getPathParams().getBegin(),
468								  params.getPathParams().getEnd()) ? 0 : 4;
469	bad |= params.setHollow(params.getProfileParams().getHollow()) ? 0 : 8;
470	bad |= params.setTwistBegin(params.getPathParams().getTwistBegin()) ? 0 : 0x10;
471	bad |= params.setTwistEnd(params.getPathParams().getTwistEnd()) ? 0 : 0x20;
472	bad |= params.setRatio(params.getPathParams().getScaleX(),
473						   params.getPathParams().getScaleY()) ? 0 : 0x40;
474	bad |= params.setShear(params.getPathParams().getShearX(),
475						   params.getPathParams().getShearY()) ? 0 : 0x80;
476	bad |= params.setTaper(params.getPathParams().getTaperX(),
477						   params.getPathParams().getTaperY()) ? 0 : 0x100;
478	bad |= params.setRevolutions(params.getPathParams().getRevolutions()) ? 0 : 0x200;
479	bad |= params.setRadiusOffset(params.getPathParams().getRadiusOffset()) ? 0 : 0x400;
480	bad |= params.setSkew(params.getPathParams().getSkew()) ? 0 : 0x800;
481	if(bad)
482	{
483		llwarns << "LLVolumeMessage::constrainVolumeParams() - "
484				<< "forced to constrain incoming volume params: "
485				<< llformat("0x%04x",bad) << llendl;
486	}
487	return bad ? false : true;
488}
489
490bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLMessageSystem *mesgsys)
491{
492	// llinfos << "pack volume" << llendl;
493	if (params)
494	{
495		packPathParams(&params->getPathParams(), mesgsys);
496		packProfileParams(&params->getProfileParams(), mesgsys);
497	}
498	else
499	{
500		packPathParams(0, mesgsys);
501		packProfileParams(0, mesgsys);
502	}
503	return true;
504}
505
506bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLDataPacker &dp)
507{
508	// llinfos << "pack volume" << llendl;
509	if (params)
510	{
511		packPathParams(&params->getPathParams(), dp);
512		packProfileParams(&params->getProfileParams(), dp);
513	}
514	else
515	{
516		packPathParams(0, dp);
517		packProfileParams(0, dp);
518	}
519	return true;
520}
521
522bool LLVolumeMessage::unpackVolumeParams(
523	LLVolumeParams* params,
524	LLMessageSystem* mesgsys,
525	char const* block_name,
526	S32 block_num)
527{
528	bool ok = true;
529	ok &= unpackPathParams(
530		&params->getPathParams(),
531		mesgsys,
532		block_name,
533		block_num);
534	ok &= unpackProfileParams(
535		&params->getProfileParams(),
536		mesgsys,
537		block_name,
538		block_num);
539	ok &= constrainVolumeParams(*params);
540		
541	return ok;
542}
543
544bool LLVolumeMessage::unpackVolumeParams(
545	LLVolumeParams* params,
546	LLDataPacker &dp)
547{
548	bool ok = true;
549	ok &= unpackPathParams(&params->getPathParams(), dp);
550	ok &= unpackProfileParams(&params->getProfileParams(), dp);
551	ok &= constrainVolumeParams(*params);
552	return ok;
553}
554
555//============================================================================