Files
SingularityViewer/indra/llmessage/llpartdata.cpp
2011-02-23 01:40:47 -06:00

352 lines
10 KiB
C++

/**
* @file llpartdata.cpp
* @brief Particle system data packing
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llpartdata.h"
#include "message.h"
#include "lldatapacker.h"
#include "v4coloru.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18
const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86
const F32 MAX_PART_SCALE = 4.f;
BOOL LLPartData::pack(LLDataPacker &dp)
{
LLColor4U coloru;
dp.packU32(mFlags, "pdflags");
dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8);
coloru.setVec(mStartColor);
dp.packColor4U(coloru, "pdstartcolor");
coloru.setVec(mEndColor);
dp.packColor4U(coloru, "pdendcolor");
dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5);
dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
return TRUE;
}
LLSD LLPartData::asLLSD() const
{
LLSD sd = LLSD();
sd["pdflags"] = ll_sd_from_U32(mFlags);
sd["pdmaxage"] = mMaxAge;
sd["pdstartcolor"] = ll_sd_from_color4(mStartColor);
sd["pdendcolor"] = ll_sd_from_color4(mEndColor);
sd["pdstartscale"] = ll_sd_from_vector2(mStartScale);
sd["pdendscale"] = ll_sd_from_vector2(mEndScale);
return sd;
}
bool LLPartData::fromLLSD(LLSD& sd)
{
mFlags = ll_U32_from_sd(sd["pdflags"]);
mMaxAge = (F32)sd["pdmaxage"].asReal();
mStartColor = ll_color4_from_sd(sd["pdstartcolor"]);
mEndColor = ll_color4_from_sd(sd["pdendcolor"]);
mStartScale = ll_vector2_from_sd(sd["pdstartscale"]);
mEndScale = ll_vector2_from_sd(sd["pdendscale"]);
return true;
}
BOOL LLPartData::unpack(LLDataPacker &dp)
{
LLColor4U coloru;
dp.unpackU32(mFlags, "pdflags");
dp.unpackFixed(mMaxAge, "pdmaxage", FALSE, 8, 8);
dp.unpackColor4U(coloru, "pdstartcolor");
mStartColor.setVec(coloru);
dp.unpackColor4U(coloru, "pdendcolor");
mEndColor.setVec(coloru);
dp.unpackFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5);
dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
return TRUE;
}
void LLPartData::setFlags(const U32 flags)
{
mFlags = flags;
}
void LLPartData::setMaxAge(const F32 max_age)
{
mMaxAge = llclamp(max_age, 0.f, 30.f);
}
void LLPartData::setStartScale(const F32 xs, const F32 ys)
{
mStartScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
mStartScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
}
void LLPartData::setEndScale(const F32 xs, const F32 ys)
{
mEndScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
mEndScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
}
void LLPartData::setStartColor(const LLVector3 &rgb)
{
mStartColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
}
void LLPartData::setEndColor(const LLVector3 &rgb)
{
mEndColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
}
void LLPartData::setStartAlpha(const F32 alpha)
{
mStartColor.mV[3] = alpha;
}
void LLPartData::setEndAlpha(const F32 alpha)
{
mEndColor.mV[3] = alpha;
}
LLPartSysData::LLPartSysData()
{
mCRC = 0;
mFlags = 0;
mPartData.mFlags = 0;
mPartData.mStartColor = LLColor4(1.f, 1.f, 1.f, 1.f);
mPartData.mEndColor = LLColor4(1.f, 1.f, 1.f, 1.f);
mPartData.mStartScale = LLVector2(1.f, 1.f);
mPartData.mEndScale = LLVector2(1.f, 1.f);
mPartData.mMaxAge = 10.0;
mMaxAge = 0.0;
mStartAge = 0.0;
mPattern = LL_PART_SRC_PATTERN_DROP; // Pattern for particle velocity
mInnerAngle = 0.0; // Inner angle of PATTERN_ANGLE_*
mOuterAngle = 0.0; // Outer angle of PATTERN_ANGLE_*
mBurstRate = 0.1f; // How often to do a burst of particles
mBurstPartCount = 1; // How many particles in a burst
mBurstSpeedMin = 1.f; // Minimum particle velocity
mBurstSpeedMax = 1.f; // Maximum particle velocity
mBurstRadius = 0.f;
mNumParticles = 0;
}
BOOL LLPartSysData::pack(LLDataPacker &dp)
{
dp.packU32(mCRC, "pscrc");
dp.packU32(mFlags, "psflags");
dp.packU8(mPattern, "pspattern");
dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8);
dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8);
dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5);
dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5);
dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8);
dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8);
dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8);
dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8);
dp.packU8(mBurstPartCount, "psburstpartcount");
dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7);
dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7);
dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7);
dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7);
dp.packUUID(mPartImageID, "psuuid");
dp.packUUID(mTargetUUID, "pstargetuuid");
mPartData.pack(dp);
return TRUE;
}
BOOL LLPartSysData::unpack(LLDataPacker &dp)
{
dp.unpackU32(mCRC, "pscrc");
dp.unpackU32(mFlags, "psflags");
dp.unpackU8(mPattern, "pspattern");
dp.unpackFixed(mMaxAge, "psmaxage", FALSE, 8, 8);
dp.unpackFixed(mStartAge, "psstartage", FALSE, 8, 8);
dp.unpackFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5);
dp.unpackFixed(mOuterAngle, "psouterangle", FALSE, 3, 5);
dp.unpackFixed(mBurstRate, "psburstrate", FALSE, 8, 8);
mBurstRate = llmax(0.01f, mBurstRate);
dp.unpackFixed(mBurstRadius, "psburstradius", FALSE, 8, 8);
dp.unpackFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8);
dp.unpackFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8);
dp.unpackU8(mBurstPartCount, "psburstpartcount");
dp.unpackFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7);
dp.unpackFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7);
dp.unpackFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7);
dp.unpackFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7);
dp.unpackFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7);
dp.unpackFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7);
dp.unpackUUID(mPartImageID, "psuuid");
dp.unpackUUID(mTargetUUID, "pstargetuuid");
mPartData.unpack(dp);
return TRUE;
}
std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
{
s << "Flags: " << std::hex << data.mFlags;
s << " Pattern: " << std::hex << (U32) data.mPattern << "\n";
s << "Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
s << "Burst Rate: " << data.mBurstRate << "\n";
s << "Burst Radius: " << data.mBurstRadius << "\n";
s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
s << "Angular Velocity: " << data.mAngularVelocity << "\n";
s << "Accel: " << data.mPartAccel;
return s;
}
BOOL LLPartSysData::isNullPS(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
U32 crc;
S32 size;
// Check size of block
size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
if (!size)
{
return TRUE;
}
else if (size != PS_DATA_BLOCK_SIZE)
{
llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
return TRUE;
}
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
dp.unpackU32(crc, "crc");
if (crc == 0)
{
return TRUE;
}
return FALSE;
}
//static
BOOL LLPartSysData::packNull()
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0);
return TRUE;
}
BOOL LLPartSysData::packBlock()
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
pack(dp);
// Add to message
gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE);
return TRUE;
}
BOOL LLPartSysData::unpackBlock(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
// Check size of block
S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
if (size != PS_DATA_BLOCK_SIZE)
{
llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
return FALSE;
}
// Get from message
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
unpack(dp);
return TRUE;
}
void LLPartSysData::clampSourceParticleRate()
{
F32 particle_rate = 0;
particle_rate = mBurstPartCount/mBurstRate;
if (particle_rate > 256.f)
{
mBurstPartCount = llfloor(((F32)mBurstPartCount)*(256.f/particle_rate));
}
}
void LLPartSysData::setPartAccel(const LLVector3 &accel)
{
mPartAccel.mV[VX] = llclamp(accel.mV[VX], -100.f, 100.f);
mPartAccel.mV[VY] = llclamp(accel.mV[VY], -100.f, 100.f);
mPartAccel.mV[VZ] = llclamp(accel.mV[VZ], -100.f, 100.f);
}