MAINT-2410 Extra Particle Parameters -- viewer implementation
Reviewed by Kelly and Grahammaster
parent
7a71c094b9
commit
08ae21f52d
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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....
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ public:
|
|||
LL_ALIGN_16(LLFace* mFace); //associated face
|
||||
F32 mDistance;
|
||||
U32 mDrawMode;
|
||||
U32 mBlendFuncSrc;
|
||||
U32 mBlendFuncDst;
|
||||
|
||||
struct CompareTexture
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ public:
|
|||
LLStrider<LLVector3>& normalsp,
|
||||
LLStrider<LLVector2>& texcoordsp,
|
||||
LLStrider<LLColor4U>& colorsp,
|
||||
LLStrider<LLColor4U>& emissivep,
|
||||
LLStrider<U16>& indicesp);
|
||||
|
||||
void updateFaceSize(S32 idx) { }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue