MAINT-2410 Extra Particle Parameters -- viewer implementation

Reviewed by Kelly and Graham
master
Dave Parks 2013-03-13 17:07:22 -05:00
parent 7a71c094b9
commit 08ae21f52d
17 changed files with 570 additions and 225 deletions

View File

@ -37,9 +37,21 @@
const S32 PS_PART_DATA_GLOW_BLEND_SIZE = 4;
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 + PS_PART_DATA_GLOW_BLEND_SIZE; // 68 + 18 + 4 = 90
const S32 PS_PART_DATA_GLOW_SIZE = 2;
const S32 PS_PART_DATA_BLEND_SIZE = 2;
const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
PS_LEGACY_PART_DATA_BLOCK_SIZE +
PS_PART_DATA_BLEND_SIZE +
PS_PART_DATA_GLOW_SIZE+
8; //two S32 size fields
const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND;
const F32 MAX_PART_SCALE = 4.f;
@ -49,28 +61,9 @@ bool LLPartData::hasGlow() const
return mStartGlow > 0.f || mEndGlow > 0.f;
}
BOOL LLPartData::pack(LLDataPacker &dp)
bool LLPartData::hasBlendFunc() const
{
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);
if (hasGlow() || hasBlendFunc())
{
dp.packU8(mStartGlow * 255,"pdstartglow");
dp.packU8(mEndGlow * 255,"pdendglow");
dp.packU8(mBlendFuncSource,"pdblendsource");
dp.packU8(mBlendFuncDest,"pdblenddest");
}
return TRUE;
return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
}
LLSD LLPartData::asLLSD() const
@ -107,8 +100,17 @@ bool LLPartData::fromLLSD(LLSD& sd)
return true;
}
S32 LLPartData::getSize() const
{
S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
BOOL LLPartData::unpack(LLDataPacker &dp)
return size;
}
BOOL LLPartData::unpackLegacy(LLDataPacker &dp)
{
LLColor4U coloru;
@ -124,7 +126,7 @@ BOOL LLPartData::unpack(LLDataPacker &dp)
dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
if (dp.hasNext())
/*if (dp.hasNext())
{
U8 tmp_glow = 0;
dp.unpackU8(tmp_glow,"pdstartglow");
@ -133,11 +135,71 @@ BOOL LLPartData::unpack(LLDataPacker &dp)
mEndGlow = tmp_glow / 255.f;
dp.unpackU8(mBlendFuncSource,"pdblendsource");
dp.unpackU8(mBlendFuncDest,"pdblenddest");
}
}*/
mStartGlow = 0.f;
mEndGlow = 0.f;
mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
return TRUE;
}
BOOL LLPartData::unpack(LLDataPacker &dp)
{
S32 size = 0;
dp.unpackS32(size, "partsize");
unpackLegacy(dp);
size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
if (mFlags & LL_PART_DATA_GLOW)
{
if (size < PS_PART_DATA_GLOW_SIZE) return FALSE;
U8 tmp_glow = 0;
dp.unpackU8(tmp_glow,"pdstartglow");
mStartGlow = tmp_glow / 255.f;
dp.unpackU8(tmp_glow,"pdendglow");
mEndGlow = tmp_glow / 255.f;
size -= PS_PART_DATA_GLOW_SIZE;
}
else
{
mStartGlow = 0.f;
mEndGlow = 0.f;
}
if (mFlags & LL_PART_DATA_BLEND)
{
if (size < PS_PART_DATA_BLEND_SIZE) return FALSE;
dp.unpackU8(mBlendFuncSource,"pdblendsource");
dp.unpackU8(mBlendFuncDest,"pdblenddest");
size -= PS_PART_DATA_BLEND_SIZE;
}
else
{
mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
}
if (size > 0)
{ //leftover bytes, unrecognized parameters
U8 feh = 0;
while (size > 0)
{ //read remaining bytes in block
dp.unpackU8(feh, "whippang");
size--;
}
//this particle system won't display properly, better to not show anything
return FALSE;
}
return TRUE;
}
void LLPartData::setFlags(const U32 flags)
{
@ -228,38 +290,7 @@ LLPartSysData::LLPartSysData()
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)
BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)
{
dp.unpackU32(mCRC, "pscrc");
dp.unpackU32(mFlags, "psflags");
@ -285,10 +316,48 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)
dp.unpackUUID(mPartImageID, "psuuid");
dp.unpackUUID(mTargetUUID, "pstargetuuid");
mPartData.unpack(dp);
return TRUE;
}
BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp)
{
unpackSystem(dp);
mPartData.unpackLegacy(dp);
return TRUE;
}
BOOL LLPartSysData::unpack(LLDataPacker &dp)
{
// syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
S32 size = 0;
dp.unpackS32(size, "syssize");
if (size != PS_SYS_DATA_BLOCK_SIZE)
{ //unexpected size, this viewer doesn't know how to parse this particle system
//skip to LLPartData block
U8 feh = 0;
for (U32 i = 0; i < size; ++i)
{
dp.unpackU8(feh, "whippang");
}
dp.unpackS32(size, "partsize");
//skip LLPartData block
for (U32 i = 0; i < size; ++i)
{
dp.unpackU8(feh, "whippang");
}
return FALSE;
}
unpackSystem(dp);
return mPartData.unpack(dp);
}
std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
{
s << "Flags: " << std::hex << data.mFlags;
@ -306,7 +375,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
BOOL LLPartSysData::isNullPS(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
U32 crc;
S32 size;
@ -318,15 +387,27 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)
return TRUE;
}
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
if (size > PS_DATA_BLOCK_SIZE)
if (size > PS_MAX_DATA_BLOCK_SIZE)
{
//size is too big, newer particle version unsupported
return TRUE;
}
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, size);
if (size > PS_LEGACY_DATA_BLOCK_SIZE)
{
// non legacy systems pack a size before the CRC
S32 tmp = 0;
dp.unpackS32(tmp, "syssize");
if (tmp > PS_SYS_DATA_BLOCK_SIZE)
{ //unknown system data block size, don't know how to parse it, treat as NULL
return TRUE;
}
}
dp.unpackU32(crc, "crc");
if (crc == 0)
@ -336,53 +417,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)
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);
S32 size = dp.getCurrentSize();
// Add to message
gMessageSystem->addBinaryData("PSBlock", ps_data_block, size);
return TRUE;
}
BOOL LLPartSysData::unpackBlock(const S32 block_num)
{
U8 ps_data_block[PS_DATA_BLOCK_SIZE];
U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
// Check size of block
S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
if (size > PS_DATA_BLOCK_SIZE)
if (size > PS_MAX_DATA_BLOCK_SIZE)
{
// Larger packets are newer and unsupported
return FALSE;
}
// Get from message
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_DATA_BLOCK_SIZE);
gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
LLDataPackerBinaryBuffer dp(ps_data_block, size);
unpack(dp);
return TRUE;
if (size == PS_LEGACY_DATA_BLOCK_SIZE)
{
return unpackLegacy(dp);
}
else
{
return unpack(dp);
}
}
bool LLPartSysData::isLegacyCompatible() const
{
return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
}
void LLPartSysData::clampSourceParticleRate()

View File

@ -88,7 +88,9 @@ public:
mParameter(0.f)
{
}
BOOL unpackLegacy(LLDataPacker &dp);
BOOL unpack(LLDataPacker &dp);
BOOL pack(LLDataPacker &dp);
LLSD asLLSD() const;
operator LLSD() const {return asLLSD(); }
@ -117,6 +119,10 @@ public:
//LL_PART_RANDOM_VEL_MASK = 0x200, // Particles have random velocity shifts"
//LL_PART_TRAIL_MASK = 0x400, // Particles have historical "trails"
//sYSTEM SET FLAGS
LL_PART_DATA_GLOW = 0x10000,
LL_PART_DATA_BLEND = 0x20000,
// Viewer side use only!
LL_PART_HUD = 0x40000000,
LL_PART_DEAD_MASK = 0x80000000,
@ -152,6 +158,9 @@ public:
friend class LLPartSysData;
friend class LLViewerPartSourceScript;
private:
S32 getSize() const;
// These are public because I'm really lazy...
public:
U32 mFlags; // Particle state/interpolators in effect
@ -178,15 +187,13 @@ public:
LLPartSysData();
BOOL unpack(LLDataPacker &dp);
BOOL pack(LLDataPacker &dp);
BOOL unpackLegacy(LLDataPacker &dp);
BOOL unpackBlock(const S32 block_num);
BOOL packBlock();
static BOOL packNull();
static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system)
bool isLegacyCompatible() const;
// Different masks for effects on the source
enum
{
@ -222,6 +229,9 @@ public:
S32 getdataBlockSize() const;
private:
BOOL unpackSystem(LLDataPacker &dp);
public:
// Public because I'm lazy....

View File

@ -2360,7 +2360,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
if (data_mask & MAP_COLOR)
{
S32 loc = TYPE_COLOR;
void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
//bind emissive instead of color pointer if emissive is present
void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
}
if (data_mask & MAP_EMISSIVE)
@ -2368,6 +2369,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
S32 loc = TYPE_EMISSIVE;
void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
if (!(data_mask & MAP_COLOR))
{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
loc = TYPE_COLOR;
glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
}
}
if (data_mask & MAP_WEIGHT)
{

View File

@ -394,10 +394,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
if (group->mSpatialPartition->mRenderByGroup &&
!group->isDead())
{
bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
// All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress.
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");
LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP);
bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow.
bool disable_cull = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE ||
group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0);
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
@ -498,32 +503,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
}
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts");
{
LLFastTimer t(FTM_RENDER_ALPHA_PUSH);
gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
params.mVertexBuffer->setBuffer(mask);
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
}
// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.
if (current_shader &&
draw_glow_for_this_partition &&
params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
{
static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GLOW("Alpha Glow");
LLFastTimer t(FTM_RENDER_ALPHA_GLOW);
// install glow-accumulating blend mode
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
emissive_shader->bind();
// glow doesn't use vertex colors from the mesh data
params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
params.mVertexBuffer->setBuffer(mask | LLVertexBuffer::MAP_EMISSIVE);
// do the actual drawing, again
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
// restore our alpha blend mode
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
current_shader->bind();
}
if (tex_setup)
@ -536,6 +540,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
}
}
gGL.setSceneBlendType(LLRender::BT_ALPHA);
LLVertexBuffer::unbind();
if (!light_enabled)

View File

@ -4654,7 +4654,9 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
mGroup(NULL),
mFace(NULL),
mDistance(0.f),
mDrawMode(LLRender::TRIANGLES)
mDrawMode(LLRender::TRIANGLES),
mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA),
mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA)
{
mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);

View File

@ -119,6 +119,8 @@ public:
LL_ALIGN_16(LLFace* mFace); //associated face
F32 mDistance;
U32 mDrawMode;
U32 mBlendFuncSrc;
U32 mBlendFuncDst;
struct CompareTexture
{

View File

@ -1553,6 +1553,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
dp->setPassFlags(value);
dp->unpackUUID(owner_id, "Owner");
mOwnerID = owner_id;
if (value & 0x80)
{
dp->unpackVector3(new_angv, "Omega");
@ -1626,13 +1628,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
retval |= checkMediaURL(media_url);
//
// Unpack particle system data
// Unpack particle system data (legacy)
//
if (value & 0x8)
{
unpackParticleSource(*dp, owner_id);
unpackParticleSource(*dp, owner_id, true);
}
else
else if (!(value & 0x400))
{
deleteParticleSource();
}
@ -1697,7 +1699,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// keep local flags and overwrite remote-controlled flags
mFlags = (mFlags & FLAGS_LOCAL) | flags;
// ...new objects that should come in selected need to be added to the selected list
// ...new objects that should come in selected need to be added to the selected list
mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
}
break;
@ -4604,7 +4606,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own
}
}
void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id)
void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy)
{
if (!mPartSourcep.isNull() && mPartSourcep->isDead())
{
@ -4613,7 +4615,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_
if (mPartSourcep)
{
// If we've got one already, just update the existing source (or remove it)
if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp))
if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy))
{
mPartSourcep->setDead();
mPartSourcep = NULL;
@ -4621,7 +4623,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_
}
else
{
LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp);
LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy);
//If the owner is muted, don't create the system
if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;
// We need to be able to deal with a particle source that hasn't changed, but still got an update!
@ -5467,6 +5469,11 @@ F32 LLAlphaObject::getPartSize(S32 idx)
return 0.f;
}
void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst)
{
}
// virtual
void LLStaticViewerObject::updateDrawable(BOOL force_damped)
{

View File

@ -584,6 +584,7 @@ public:
} EPhysicsShapeType;
LLUUID mID;
LLUUID mOwnerID; //null if unknown
// unique within region, not unique across regions
// Local ID = 0 is not used
@ -662,7 +663,7 @@ protected:
BOOL isOnMap();
void unpackParticleSource(const S32 block_num, const LLUUID& owner_id);
void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id);
void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);
void deleteParticleSource();
void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
@ -826,9 +827,12 @@ public:
LLStrider<LLVector4a>& verticesp,
LLStrider<LLVector3>& normalsp,
LLStrider<LLVector2>& texcoordsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp) = 0;
virtual void getBlendFunc(S32 face, U32& src, U32& dst);
F32 mDepth;
};

View File

@ -80,12 +80,31 @@ LLViewerPart::LLViewerPart() :
mImagep(NULL)
{
mPartSourcep = NULL;
mParent = NULL;
mChild = NULL;
++LLViewerPartSim::sParticleCount2 ;
}
LLViewerPart::~LLViewerPart()
{
if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this)
{
mPartSourcep->mLastPart = NULL;
}
//patch up holes in the ribbon
if (mParent)
{
llassert(mParent->mChild == this);
mParent->mChild = mChild;
}
if (mChild)
{
llassert (mChild->mParent == this);
mChild->mParent = mParent;
}
mPartSourcep = NULL;
--LLViewerPartSim::sParticleCount2 ;
@ -367,6 +386,9 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)
part->mScale += frac*part->mEndScale;
}
// Do glow interpolation
part->mGlow.mV[3] = (U8) (lerp(part->mStartGlow, part->mEndGlow, frac)*255.f);
// Set the last update time to now.
part->mLastUpdateTime = cur_time;
@ -623,6 +645,9 @@ void LLViewerPartSim::updateSimulation()
{
static LLFrameTimer update_timer;
//reset VBO cursor
LLVOPartGroup::sVBSlotCursor = 0;
const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))

View File

@ -65,15 +65,22 @@ public:
LLVPCallback mVPCallback; // Callback function for more complicated behaviors
LLPointer<LLViewerPartSource> mPartSourcep; // Particle source used for this object
LLViewerPart* mParent; // particle to connect to if this is part of a particle ribbon
LLViewerPart* mChild; // child particle for clean reference destruction
// Current particle state (possibly used for rendering)
LLPointer<LLViewerTexture> mImagep;
LLVector3 mPosAgent;
LLVector3 mVelocity;
LLVector3 mAccel;
LLVector3 mAxis;
LLColor4 mColor;
LLVector2 mScale;
F32 mStartGlow;
F32 mEndGlow;
LLColor4U mGlow;
static U32 sNextPartID;
};

View File

@ -52,6 +52,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) :
static U32 id_seed = 0;
mID = ++id_seed;
mLastPart = NULL;
mDelay = 0 ;
}
@ -279,6 +281,22 @@ void LLViewerPartSourceScript::update(const F32 dt)
{
part->mFlags |= LLPartData::LL_PART_HUD;
}
if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart)
{ //set previous particle's parent to this particle to chain ribbon together
mLastPart->mParent = part;
part->mChild = mLastPart;
part->mAxis = LLVector3(0,0,1);
if (mSourceObjectp.notNull())
{
LLQuaternion rot = mSourceObjectp->getRenderRotation();
part->mAxis *= rot;
}
}
mLastPart = part;
part->mMaxAge = mPartSysData.mPartData.mMaxAge;
part->mStartColor = mPartSysData.mPartData.mStartColor;
part->mEndColor = mPartSysData.mPartData.mEndColor;
@ -290,6 +308,13 @@ void LLViewerPartSourceScript::update(const F32 dt)
part->mAccel = mPartSysData.mPartAccel;
part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest;
part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource;
part->mStartGlow = mPartSysData.mPartData.mStartGlow;
part->mEndGlow = mPartSysData.mPartData.mEndGlow;
part->mGlow = LLColor4U(0, 0, 0, (U8) (part->mStartGlow*255.f));
if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
{
part->mPosAgent = mPosAgent;
@ -430,28 +455,51 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer
}
LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp)
LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy)
{
if (!pssp)
{
LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
if (!new_pssp->mPartSysData.unpack(dp))
if (legacy)
{
return NULL;
if (!new_pssp->mPartSysData.unpackLegacy(dp))
{
return NULL;
}
}
else
{
if (!new_pssp->mPartSysData.unpack(dp))
{
return NULL;
}
}
if (new_pssp->mPartSysData.mTargetUUID.notNull())
{
LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
new_pssp->setTargetObject(target_objp);
}
return new_pssp;
}
else
{
if (!pssp->mPartSysData.unpack(dp))
if (legacy)
{
return NULL;
if (!pssp->mPartSysData.unpackLegacy(dp))
{
return NULL;
}
}
else
{
if (!pssp->mPartSysData.unpack(dp))
{
return NULL;
}
}
if (pssp->mPartSysData.mTargetUUID.notNull())
{
LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
@ -569,6 +617,11 @@ void LLViewerPartSourceSpiral::update(const F32 dt)
part->mScale.mV[0] = 0.25f;
part->mScale.mV[1] = 0.25f;
part->mParameter = ll_frand(F_TWO_PI);
part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
part->mStartGlow = 0.f;
part->mEndGlow = 0.f;
part->mGlow = LLColor4U(0, 0, 0, 0);
LLViewerPartSim::getInstance()->addPart(part);
}
@ -721,6 +774,12 @@ void LLViewerPartSourceBeam::update(const F32 dt)
part->mPosAgent = mPosAgent;
part->mVelocity = mTargetPosAgent - mPosAgent;
part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
part->mStartGlow = 0.f;
part->mEndGlow = 0.f;
part->mGlow = LLColor4U(0, 0, 0, 0);
LLViewerPartSim::getInstance()->addPart(part);
}
}
@ -825,6 +884,12 @@ void LLViewerPartSourceChat::update(const F32 dt)
part->mScale.mV[0] = 0.25f;
part->mScale.mV[1] = 0.25f;
part->mParameter = ll_frand(F_TWO_PI);
part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
part->mStartGlow = 0.f;
part->mEndGlow = 0.f;
part->mGlow = LLColor4U(0, 0, 0, 0);
LLViewerPartSim::getInstance()->addPart(part);
}

View File

@ -76,6 +76,7 @@ public:
LLVector3 mLastUpdatePosAgent;
LLPointer<LLViewerObject> mSourceObjectp;
U32 mID;
LLViewerPart* mLastPart; //last particle emitted (for making particle ribbons)
protected:
U32 mType;
@ -85,7 +86,6 @@ protected:
F32 mLastPartTime;
LLUUID mOwnerUUID;
LLPointer<LLViewerTexture> mImagep;
// Particle information
U32 mPartFlags; // Flags for the particle
U32 mDelay ; //delay to start particles
@ -114,7 +114,7 @@ public:
// Returns a new particle source to attach to an object...
static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num);
static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp);
static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy);
static LLPointer<LLViewerPartSourceScript> createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters);
LLViewerTexture *getImage() const { return mImagep; }

View File

@ -476,6 +476,7 @@ void LLVOGrass::getGeometry(S32 idx,
LLStrider<LLVector3>& normalsp,
LLStrider<LLVector2>& texcoordsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp)
{
if(!mNumBlades)//stop rendering grass
@ -708,7 +709,11 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)
facep->setIndicesIndex(index_count);
facep->setVertexBuffer(buffer);
facep->setPoolType(LLDrawPool::POOL_ALPHA);
object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp);
//dummy parameter (unused by this implementation)
LLStrider<LLColor4U> emissivep;
object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, emissivep, indicesp);
vertex_count += facep->getGeomCount();
index_count += facep->getIndicesCount();

View File

@ -63,6 +63,7 @@ public:
LLStrider<LLVector3>& normalsp,
LLStrider<LLVector2>& texcoordsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp);
void updateFaceSize(S32 idx) { }

View File

@ -49,17 +49,11 @@ const F32 MAX_PART_LIFETIME = 120.f;
extern U64 gFrameTime;
LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL;
S32 LLVOPartGroup::sVBSlotFree[];
S32* LLVOPartGroup::sVBSlotCursor = NULL;
S32 LLVOPartGroup::sVBSlotCursor = 0;
void LLVOPartGroup::initClass()
{
for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i)
{
sVBSlotFree[i] = i;
}
sVBSlotCursor = sVBSlotFree;
}
//static
@ -122,36 +116,33 @@ void LLVOPartGroup::destroyGL()
//static
S32 LLVOPartGroup::findAvailableVBSlot()
{
if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT)
if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)
{ //no more available slots
return -1;
}
S32 ret = *sVBSlotCursor;
sVBSlotCursor++;
return ret;
return sVBSlotCursor++;
}
bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)
{
while (start < end)
/*while (start < end)
{
if (*start == idx)
{ //not allocated (in free list)
return false;
}
++start;
}
}*/
//allocated (not in free list)
return true;
return false;
}
//static
void LLVOPartGroup::freeVBSlot(S32 idx)
{
llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);
llassert(sVBSlotCursor > sVBSlotFree);
llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT));
@ -159,7 +150,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)
{
sVBSlotCursor--;
*sVBSlotCursor = idx;
}
}*/
}
LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
@ -189,6 +180,7 @@ F32 LLVOPartGroup::getBinRadius()
void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
{
const LLVector3& pos_agent = getPositionAgent();
newMin.load3( (pos_agent - mScale).mV);
newMax.load3( (pos_agent + mScale).mV);
LLVector4a pos;
@ -273,6 +265,16 @@ F32 LLVOPartGroup::getPartSize(S32 idx)
return 0.f;
}
void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst)
{
if (idx < (S32) mViewerPartGroupp->mParticles.size())
{
LLViewerPart* part = mViewerPartGroupp->mParticles[idx];
src = part->mBlendFuncSource;
dst = part->mBlendFuncDest;
}
}
LLVector3 LLVOPartGroup::getCameraPosition() const
{
return gAgentCamera.getCameraPositionAgent();
@ -332,13 +334,42 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
mDepth = 0.f;
S32 i = 0 ;
LLVector3 camera_agent = getCameraPosition();
F32 max_scale = 0.f;
for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)
{
const LLViewerPart *part = mViewerPartGroupp->mParticles[i];
//remember the largest particle
max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]);
if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK)
{ //include ribbon segment length in scale
const LLVector3* pos_agent = NULL;
if (part->mParent)
{
pos_agent = &(part->mParent->mPosAgent);
}
else if (part->mPartSourcep.notNull())
{
pos_agent = &(part->mPartSourcep->mPosAgent);
}
if (pos_agent)
{
F32 dist = (*pos_agent-part->mPosAgent).length();
max_scale = llmax(max_scale, dist);
}
}
LLVector3 part_pos_agent(part->mPosAgent);
LLVector3 at(part_pos_agent - camera_agent);
F32 camera_dist_squared = at.lengthSquared();
F32 inv_camera_dist_squared;
if (camera_dist_squared > 1.f)
@ -411,6 +442,9 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
facep->setSize(0, 0);
}
//record max scale (used to stretch bounding box for visibility culling)
mScale.set(max_scale, max_scale, max_scale);
mDrawable->movePartition();
LLPipeline::sCompiles++;
return TRUE;
@ -478,74 +512,129 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector3& start, const LLVector3
void LLVOPartGroup::getGeometry(const LLViewerPart& part,
LLStrider<LLVector4a>& verticesp)
{
LLVector4a part_pos_agent;
part_pos_agent.load3(part.mPosAgent.mV);
LLVector4a camera_agent;
camera_agent.load3(getCameraPosition().mV);
LLVector4a at;
at.setSub(part_pos_agent, camera_agent);
LLVector4a up(0, 0, 1);
LLVector4a right;
right.setCross3(at, up);
right.normalize3fast();
up.setCross3(right, at);
up.normalize3fast();
if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)
if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)
{
LLVector4a normvel;
normvel.load3(part.mVelocity.mV);
normvel.normalize3fast();
LLVector2 up_fracs;
up_fracs.mV[0] = normvel.dot3(right).getF32();
up_fracs.mV[1] = normvel.dot3(up).getF32();
up_fracs.normalize();
LLVector4a new_up;
LLVector4a new_right;
LLVector4a axis, pos, paxis, ppos;
F32 scale, pscale;
//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up;
LLVector4a t = right;
t.mul(up_fracs.mV[0]);
new_up = up;
new_up.mul(up_fracs.mV[1]);
new_up.add(t);
pos.load3(part.mPosAgent.mV);
axis.load3(part.mAxis.mV);
scale = part.mScale.mV[0];
if (part.mParent)
{
ppos.load3(part.mParent->mPosAgent.mV);
paxis.load3(part.mParent->mAxis.mV);
pscale = part.mParent->mScale.mV[0];
}
else
{ //use source object as position
if (part.mPartSourcep->mSourceObjectp.notNull())
{
LLVector3 v = LLVector3(0,0,1);
v *= part.mPartSourcep->mSourceObjectp->getRenderRotation();
paxis.load3(v.mV);
ppos.load3(part.mPartSourcep->mPosAgent.mV);
pscale = part.mStartScale.mV[0];
}
else
{ //no source object, no parent, nothing to draw
ppos = pos;
pscale = scale;
paxis = axis;
}
}
//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up;
t = right;
t.mul(up_fracs.mV[1]);
new_right = up;
new_right.mul(up_fracs.mV[0]);
t.sub(new_right);
LLVector4a p0, p1, p2, p3;
up = new_up;
right = t;
up.normalize3fast();
right.normalize3fast();
scale *= 0.5f;
pscale *= 0.5f;
axis.mul(scale);
paxis.mul(pscale);
p0.setAdd(pos, axis);
p1.setSub(pos,axis);
p2.setAdd(ppos, paxis);
p3.setSub(ppos, paxis);
(*verticesp++) = p2;
(*verticesp++) = p3;
(*verticesp++) = p0;
(*verticesp++) = p1;
}
else
{
LLVector4a part_pos_agent;
part_pos_agent.load3(part.mPosAgent.mV);
LLVector4a camera_agent;
camera_agent.load3(getCameraPosition().mV);
LLVector4a at;
at.setSub(part_pos_agent, camera_agent);
LLVector4a up(0, 0, 1);
LLVector4a right;
right.mul(0.5f*part.mScale.mV[0]);
up.mul(0.5f*part.mScale.mV[1]);
right.setCross3(at, up);
right.normalize3fast();
up.setCross3(right, at);
up.normalize3fast();
if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)
{
LLVector4a normvel;
normvel.load3(part.mVelocity.mV);
normvel.normalize3fast();
LLVector2 up_fracs;
up_fracs.mV[0] = normvel.dot3(right).getF32();
up_fracs.mV[1] = normvel.dot3(up).getF32();
up_fracs.normalize();
LLVector4a new_up;
LLVector4a new_right;
//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up;
LLVector4a t = right;
t.mul(up_fracs.mV[0]);
new_up = up;
new_up.mul(up_fracs.mV[1]);
new_up.add(t);
//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up;
t = right;
t.mul(up_fracs.mV[1]);
new_right = up;
new_right.mul(up_fracs.mV[0]);
t.sub(new_right);
up = new_up;
right = t;
up.normalize3fast();
right.normalize3fast();
}
right.mul(0.5f*part.mScale.mV[0]);
up.mul(0.5f*part.mScale.mV[1]);
//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
// this works because there is actually a 4th float stored after the vertex position which is used as a texture index
// also, somebody please VECTORIZE THIS
//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should)
// this works because there is actually a 4th float stored after the vertex position which is used as a texture index
// also, somebody please VECTORIZE THIS
LLVector4a ppapu;
LLVector4a ppamu;
LLVector4a ppapu;
LLVector4a ppamu;
ppapu.setAdd(part_pos_agent, up);
ppamu.setSub(part_pos_agent, up);
ppapu.setAdd(part_pos_agent, up);
ppamu.setSub(part_pos_agent, up);
verticesp->setSub(ppapu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setSub(ppamu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setAdd(ppapu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setAdd(ppamu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setSub(ppapu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setSub(ppamu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setAdd(ppapu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
verticesp->setAdd(ppamu, right);
(*verticesp++).getF32ptr()[3] = 0.f;
}
}
@ -555,6 +644,7 @@ void LLVOPartGroup::getGeometry(S32 idx,
LLStrider<LLVector3>& normalsp,
LLStrider<LLVector2>& texcoordsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp)
{
if (idx >= (S32) mViewerPartGroupp->mParticles.size())
@ -566,10 +656,40 @@ void LLVOPartGroup::getGeometry(S32 idx,
getGeometry(part, verticesp);
*colorsp++ = part.mColor;
*colorsp++ = part.mColor;
*colorsp++ = part.mColor;
*colorsp++ = part.mColor;
LLColor4U pcolor;
LLColor4U color = part.mColor;
LLColor4U pglow;
if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)
{ //make sure color blends properly
if (part.mParent)
{
pglow = part.mParent->mGlow;
pcolor = part.mParent->mColor;
}
else
{
pglow = LLColor4U(0, 0, 0, (U8) (255.f*part.mStartGlow));
pcolor = part.mStartColor;
}
}
else
{
pglow = part.mGlow;
pcolor = color;
}
*colorsp++ = pcolor;
*colorsp++ = pcolor;
*colorsp++ = color;
*colorsp++ = color;
*emissivep++ = pglow;
*emissivep++ = pglow;
*emissivep++ = part.mGlow;
*emissivep++ = part.mGlow;
if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))
{ //not fullbright, needs normal
@ -712,10 +832,13 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLStrider<LLVector3> normalsp;
LLStrider<LLVector2> texcoordsp;
LLStrider<LLColor4U> colorsp;
LLStrider<LLColor4U> emissivep;
buffer->getVertexStrider(verticesp);
buffer->getNormalStrider(normalsp);
buffer->getColorStrider(colorsp);
buffer->getEmissiveStrider(emissivep);
LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];
@ -724,7 +847,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLFace* facep = *i;
LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject();
if (!facep->isState(LLFace::PARTICLE))
//if (!facep->isState(LLFace::PARTICLE))
{ //set the indices of this face
S32 idx = LLVOPartGroup::findAvailableVBSlot();
if (idx >= 0)
@ -733,7 +856,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
facep->setIndicesIndex(idx*6);
facep->setVertexBuffer(LLVOPartGroup::sVB);
facep->setPoolType(LLDrawPool::POOL_ALPHA);
facep->setState(LLFace::PARTICLE);
//facep->setState(LLFace::PARTICLE);
}
else
{
@ -748,8 +871,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
LLStrider<LLVector3> cur_norm = normalsp + geom_idx;
LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx;
LLStrider<LLColor4U> cur_col = colorsp + geom_idx;
LLStrider<LLColor4U> cur_glow = emissivep + geom_idx;
object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx);
object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx);
llassert(facep->getGeomCount() == 4);
llassert(facep->getIndicesCount() == 6);
@ -765,9 +889,16 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
bool batched = false;
U32 bf_src = LLRender::BF_SOURCE_ALPHA;
U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst);
if (idx >= 0 &&
draw_vec[idx]->mTexture == facep->getTexture() &&
draw_vec[idx]->mFullbright == fullbright)
draw_vec[idx]->mFullbright == fullbright &&
draw_vec[idx]->mBlendFuncDst == bf_dst &&
draw_vec[idx]->mBlendFuncSrc == bf_src)
{
if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1)
{
@ -799,6 +930,8 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)
info->mExtents[0] = group->mObjectExtents[0];
info->mExtents[1] = group->mObjectExtents[1];
info->mVSize = vsize;
info->mBlendFuncDst = bf_dst;
info->mBlendFuncSrc = bf_src;
draw_vec.push_back(info);
//for alpha sorting
facep->setDrawInfo(info);

View File

@ -42,8 +42,7 @@ public:
//vertex buffer for holding all particles
static LLPointer<LLVertexBuffer> sVB;
static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT];
static S32* sVBSlotCursor;
static S32 sVBSlotCursor;
static void initClass();
static void restoreGL();
@ -57,6 +56,7 @@ public:
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TEXCOORD0 |
LLVertexBuffer::MAP_COLOR |
LLVertexBuffer::MAP_EMISSIVE |
LLVertexBuffer::MAP_TEXTURE_INDEX
};
@ -91,10 +91,12 @@ public:
LLStrider<LLVector3>& normalsp,
LLStrider<LLVector2>& texcoordsp,
LLStrider<LLColor4U>& colorsp,
LLStrider<LLColor4U>& emissivep,
LLStrider<U16>& indicesp);
void updateFaceSize(S32 idx) { }
F32 getPartSize(S32 idx);
void getBlendFunc(S32 idx, U32& src, U32& dst);
LLUUID getPartOwner(S32 idx);
LLUUID getPartSource(S32 idx);

View File

@ -384,7 +384,6 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
}
else
{
// CORY TO DO: Figure out how to get the value here
if (update_type != OUT_TERSE_IMPROVED)
{
LLVolumeParams volume_params;
@ -453,6 +452,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
mFaceMappingChanged = TRUE;
mTexAnimMode = 0;
}
if (value & 0x400)
{ //particle system (new)
unpackParticleSource(*dp, mOwnerID, false);
}
}
else
{