summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerpartsim.cpp
diff options
context:
space:
mode:
authorSteven Bennetts <steve@lindenlab.com>2007-03-02 21:25:50 +0000
committerSteven Bennetts <steve@lindenlab.com>2007-03-02 21:25:50 +0000
commit4dabd9c0472deb49573fdafef2fa413e59703f19 (patch)
tree06c680d6a2047e03838d6548bccd26c7baf9d652 /indra/newview/llviewerpartsim.cpp
parentd4462963c6ba5db2088723bbedc7b60f1184c594 (diff)
merge release@58699 beta-1-14-0@58707 -> release
Diffstat (limited to 'indra/newview/llviewerpartsim.cpp')
-rw-r--r--indra/newview/llviewerpartsim.cpp305
1 files changed, 181 insertions, 124 deletions
diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp
index db18b74d1f..a6895aff2f 100644
--- a/indra/newview/llviewerpartsim.cpp
+++ b/indra/newview/llviewerpartsim.cpp
@@ -13,6 +13,7 @@
#include "llviewercontrol.h"
#include "llagent.h"
+#include "llviewercamera.h"
#include "llviewerobjectlist.h"
#include "llviewerpartsource.h"
#include "llviewerregion.h"
@@ -22,7 +23,7 @@
const S32 MAX_PART_COUNT = 4096;
-const F32 PART_SIM_BOX_SIDE = 32.f;
+const F32 PART_SIM_BOX_SIDE = 16.f;
const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE;
const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE;
@@ -33,18 +34,28 @@ S32 LLViewerPartSim::sParticleCount = 0;
U32 LLViewerPart::sNextPartID = 1;
+F32 calc_desired_size(LLVector3 pos, LLVector2 scale)
+{
+ F32 desired_size = (pos-gCamera->getOrigin()).magVec();
+ desired_size /= 4;
+ return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2);
+}
+
LLViewerPart::LLViewerPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartSourcep = NULL;
}
LLViewerPart::~LLViewerPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartSourcep = NULL;
}
LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartID = part.mPartID;
mFlags = part.mFlags;
mMaxAge = part.mMaxAge;
@@ -74,6 +85,7 @@ LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part)
void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVPCallback cb)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mPartID = LLViewerPart::sNextPartID;
LLViewerPart::sNextPartID++;
mFlags = 0x00f;
@@ -96,8 +108,13 @@ void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVP
LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 box_side)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mVOPartGroupp = NULL;
+ mUniformParticles = TRUE;
+
mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent);
+ llassert_always(center_agent.isFinite());
+
if (!mRegionp)
{
//llwarns << "No region at position, using agent region!" << llendl;
@@ -106,28 +123,39 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 &center_agent, const F32 bo
mCenterAgent = center_agent;
mBoxRadius = F_SQRT3*box_side*0.5f;
- LLVector3 rad_vec(box_side*0.5f, box_side*0.5f, box_side*0.5f);
- rad_vec += LLVector3(0.001f, 0.001f, 0.001f);
- mMinObjPos = mCenterAgent - rad_vec;
- mMaxObjPos = mCenterAgent + rad_vec;
+ mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
+ mVOPartGroupp->setViewerPartGroup(this);
+ mVOPartGroupp->setPositionAgent(getCenterAgent());
+ F32 scale = box_side * 0.5f;
+ mVOPartGroupp->setScale(LLVector3(scale,scale,scale));
+ gPipeline.addObject(mVOPartGroupp);
+
+ LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup();
+
+ LLVector3 center(group->mOctreeNode->getCenter());
+ LLVector3 size(group->mOctreeNode->getSize());
+ size += LLVector3(0.01f, 0.01f, 0.01f);
+ mMinObjPos = center - size;
+ mMaxObjPos = center + size;
+
+ static U32 id_seed = 0;
+ mID = ++id_seed;
}
LLViewerPartGroup::~LLViewerPartGroup()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
cleanup();
- S32 count = mParticles.count();
- S32 i;
-
- for (i = 0; i < count; i++)
- {
- mParticles[i].mPartSourcep = NULL;
- }
- mParticles.reset();
+
+ S32 count = (S32) mParticles.size();
+ mParticles.clear();
+
LLViewerPartSim::decPartCount(count);
}
void LLViewerPartGroup::cleanup()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (mVOPartGroupp)
{
if (!mVOPartGroupp->isDead())
@@ -138,8 +166,9 @@ void LLViewerPartGroup::cleanup()
}
}
-BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos)
+BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if ((pos.mV[VX] < mMinObjPos.mV[VX])
|| (pos.mV[VY] < mMinObjPos.mV[VY])
|| (pos.mV[VZ] < mMinObjPos.mV[VZ]))
@@ -154,29 +183,33 @@ BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos)
return FALSE;
}
+ if (desired_size > 0 &&
+ (desired_size < mBoxRadius*0.5f ||
+ desired_size > mBoxRadius*2.f))
+ {
+ return FALSE;
+ }
+
return TRUE;
}
-BOOL LLViewerPartGroup::addPart(LLViewerPart &part)
+BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size)
{
- if (!posInGroup(part.mPosAgent) ||
- (mVOPartGroupp.notNull() && (part.mImagep != mVOPartGroupp->getTEImage(0))))
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] &&
+ !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK);
+
+ if (!posInGroup(part->mPosAgent, desired_size) ||
+ (mUniformParticles && !uniform_part) ||
+ (!mUniformParticles && uniform_part))
{
return FALSE;
}
- if (!mVOPartGroupp)
- {
- mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion());
- mVOPartGroupp->setViewerPartGroup(this);
- mVOPartGroupp->setPositionAgent(getCenterAgent());
- mVOPartGroupp->setScale(LLVector3(PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE));
- mVOPartGroupp->setTEImage(0, part.mImagep);
- gPipeline.addObject(mVOPartGroupp);
- }
+ gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
- mParticles.put(part);
+ mParticles.push_back(part);
LLViewerPartSim::incPartCount(1);
return TRUE;
}
@@ -184,33 +217,29 @@ BOOL LLViewerPartGroup::addPart(LLViewerPart &part)
void LLViewerPartGroup::removePart(const S32 part_num)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
// Remove the entry for the particle we just deleted.
- LLPointer<LLViewerPartSource> ps = mParticles[mParticles.count() - 1].mPartSourcep;
-
- mParticles[mParticles.count() - 1].mPartSourcep = NULL;
- mParticles.remove(part_num);
- if (part_num < mParticles.count())
+ mParticles.erase(mParticles.begin() + part_num);
+ if (mVOPartGroupp.notNull())
{
- mParticles[part_num].mPartSourcep = ps;
+ gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
}
-
LLViewerPartSim::decPartCount(1);
}
-
void LLViewerPartGroup::updateParticles(const F32 dt)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
S32 i, count;
-
-
+
LLVector3 gravity(0.f, 0.f, -9.8f);
LLViewerRegion *regionp = getRegion();
- count = mParticles.count();
+ count = (S32) mParticles.size();
for (i = 0; i < count; i++)
{
LLVector3 a(0.f, 0.f, 0.f);
- LLViewerPart &part = mParticles[i];
+ LLViewerPart& part = *((LLViewerPart*) mParticles[i]);
// Update current time
const F32 cur_time = part.mLastUpdateTime + dt;
@@ -252,8 +281,6 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
part.mVelocity *= (1.f - step);
part.mVelocity += step*delta_pos;
- //part.mPosAgent *= 1.f - to_target_frac;
- //part.mPosAgent += to_target_frac*part.mPartSourcep->mTargetPosAgent;
}
@@ -322,18 +349,22 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
i--;
count--;
}
- else if (!posInGroup(part.mPosAgent))
+ else
{
- // Transfer particles between groups
- gWorldPointer->mPartSim.put(part);
- removePart(i);
- i--;
- count--;
+ F32 desired_size = calc_desired_size(part.mPosAgent, part.mScale);
+ if (!posInGroup(part.mPosAgent, desired_size))
+ {
+ // Transfer particles between groups
+ gWorldPointer->mPartSim.put(&part);
+ removePart(i);
+ i--;
+ count--;
+ }
}
}
// Kill the viewer object if this particle group is empty
- if (!mParticles.count())
+ if (mParticles.empty())
{
gObjectList.killObject(mVOPartGroupp);
mVOPartGroupp = NULL;
@@ -343,15 +374,16 @@ void LLViewerPartGroup::updateParticles(const F32 dt)
void LLViewerPartGroup::shift(const LLVector3 &offset)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
mCenterAgent += offset;
mMinObjPos += offset;
mMaxObjPos += offset;
- S32 count = mParticles.count();
+ S32 count = (S32) mParticles.size();
S32 i;
for (i = 0; i < count; i++)
{
- mParticles[i].mPosAgent += offset;
+ mParticles[i]->mPosAgent += offset;
}
}
@@ -365,34 +397,34 @@ void LLViewerPartGroup::shift(const LLVector3 &offset)
LLViewerPartSim::LLViewerPartSim()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount");
+ static U32 id_seed = 0;
+ mID = ++id_seed;
}
LLViewerPartSim::~LLViewerPartSim()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
S32 i;
S32 count;
// Kill all of the groups (and particles)
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
delete mViewerPartGroups[i];
}
- mViewerPartGroups.reset();
+ mViewerPartGroups.clear();
// Kill all of the sources
- count = mViewerPartSources.count();
- for (i = 0; i < count; i++)
- {
- mViewerPartSources[i] = NULL;
- }
- mViewerPartSources.reset();
+ mViewerPartSources.clear();
}
BOOL LLViewerPartSim::shouldAddPart()
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (sParticleCount > 0.75f*sMaxParticleCount)
{
@@ -413,33 +445,35 @@ BOOL LLViewerPartSim::shouldAddPart()
return TRUE;
}
-void LLViewerPartSim::addPart(LLViewerPart &part)
+void LLViewerPartSim::addPart(LLViewerPart* part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (sParticleCount < MAX_PART_COUNT)
{
put(part);
}
}
-LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part)
+
+LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
- if (part.mPosAgent.magVecSquared() > MAX_MAG)
+ if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite())
{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
+#if !LL_RELEASE_FOR_DOWNLOAD
llwarns << "LLViewerPartSim::put Part out of range!" << llendl;
- llwarns << part.mPosAgent << llendl;
+ llwarns << part->mPosAgent << llendl;
#endif
return NULL;
}
+
+ F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale);
- S32 i;
- S32 count;
-
- count = mViewerPartGroups.count();
- for (i = 0; i < count; i++)
+ S32 count = (S32) mViewerPartGroups.size();
+ for (S32 i = 0; i < count; i++)
{
- if (mViewerPartGroups[i]->addPart(part))
+ if (mViewerPartGroups[i]->addPart(part, desired_size))
{
// We found a spatial group that we fit into, add us and exit
return mViewerPartGroups[i];
@@ -448,43 +482,27 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part)
// Hmm, we didn't fit in any of the existing spatial groups
// Create a new one...
- LLViewerPartGroup *groupp = createViewerPartGroup(part.mPosAgent);
+ llassert_always(part->mPosAgent.isFinite());
+ LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size);
+ groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] &&
+ !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK));
if (!groupp->addPart(part))
{
llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl;
llinfos << groupp->getCenterAgent() << llendl;
- llinfos << part.mPosAgent << llendl;
+ llinfos << part->mPosAgent << llendl;
return NULL;
}
return groupp;
}
-LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent)
+LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size)
{
- F32 x_origin = ((S32)(pos_agent.mV[VX]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (x_origin > pos_agent.mV[VX])
- {
- x_origin -= PART_SIM_BOX_SIDE;
- }
-
- F32 y_origin = ((S32)(pos_agent.mV[VY]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (y_origin > pos_agent.mV[VY])
- {
- y_origin -= PART_SIM_BOX_SIDE;
- }
-
- F32 z_origin = ((S32)(pos_agent.mV[VZ]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE;
- if (z_origin > pos_agent.mV[VZ])
- {
- z_origin -= PART_SIM_BOX_SIDE;
- }
-
- LLVector3 group_center(x_origin + PART_SIM_BOX_OFFSET,
- y_origin + PART_SIM_BOX_OFFSET,
- z_origin + PART_SIM_BOX_OFFSET);
-
- LLViewerPartGroup *groupp = new LLViewerPartGroup(group_center, PART_SIM_BOX_SIDE);
- mViewerPartGroups.put(groupp);
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses
+ //pos_agent
+ LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size);
+ mViewerPartGroups.push_back(groupp);
return groupp;
}
@@ -494,7 +512,7 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
S32 i;
S32 count;
- count = mViewerPartSources.count();
+ count = (S32) mViewerPartSources.size();
for (i = 0; i < count; i++)
{
mViewerPartSources[i]->mPosAgent += offset;
@@ -502,13 +520,20 @@ void LLViewerPartSim::shift(const LLVector3 &offset)
mViewerPartSources[i]->mLastUpdatePosAgent += offset;
}
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
mViewerPartGroups[i]->shift(offset);
}
}
+S32 dist_rate_func(F32 distance)
+{
+ //S32 dist = (S32) sqrtf(distance);
+ //dist /= 2;
+ //return llmax(dist,1);
+ return 1;
+}
void LLViewerPartSim::updateSimulation()
{
@@ -523,13 +548,15 @@ void LLViewerPartSim::updateSimulation()
return;
}
+ LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES);
+
// Start at a random particle system so the same
// particle system doesn't always get first pick at the
// particles. Theoretically we'd want to do this in distance
// order or something, but sorting particle sources will be a big
// pain.
S32 i;
- S32 count = mViewerPartSources.count();
+ S32 count = (S32) mViewerPartSources.size();
S32 start = (S32)ll_frand((F32)count);
S32 dir = 1;
if (ll_frand() > 0.5f)
@@ -551,12 +578,24 @@ void LLViewerPartSim::updateSimulation()
if (!mViewerPartSources[i]->isDead())
{
- mViewerPartSources[i]->update(dt);
+ LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp;
+ if (source_object && source_object->mDrawable.notNull())
+ {
+ S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera);
+ if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0)
+ {
+ mViewerPartSources[i]->update(dt*dist);
+ }
+ }
+ else
+ {
+ mViewerPartSources[i]->update(dt);
+ }
}
if (mViewerPartSources[i]->isDead())
{
- mViewerPartSources.remove(i);
+ mViewerPartSources.erase(mViewerPartSources.begin() + i);
count--;
}
else
@@ -567,16 +606,36 @@ void LLViewerPartSim::updateSimulation()
}
- count = mViewerPartGroups.count();
+ count = (S32) mViewerPartGroups.size();
for (i = 0; i < count; i++)
{
- mViewerPartGroups[i]->updateParticles(dt);
- if (!mViewerPartGroups[i]->getCount())
+ LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp;
+
+ S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ?
+ dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1;
+ if (vobj)
{
- delete mViewerPartGroups[i];
- mViewerPartGroups.remove(i);
- i--;
- count--;
+ LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup();
+ if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY))
+ {
+ dist *= 8;
+ }
+ }
+
+ if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0)
+ {
+ if (vobj)
+ {
+ gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ mViewerPartGroups[i]->updateParticles(dt*dist);
+ if (!mViewerPartGroups[i]->getCount())
+ {
+ delete mViewerPartGroups[i];
+ mViewerPartGroups.erase(mViewerPartGroups.begin() + i);
+ i--;
+ count--;
+ }
}
}
//llinfos << "Particles: " << sParticleCount << llendl;
@@ -585,42 +644,40 @@ void LLViewerPartSim::updateSimulation()
void LLViewerPartSim::addPartSource(LLViewerPartSource *sourcep)
{
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
if (!sourcep)
{
llwarns << "Null part source!" << llendl;
return;
}
- mViewerPartSources.put(sourcep);
+ mViewerPartSources.push_back(sourcep);
}
void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp)
{
- S32 i, count;
- count = mViewerPartGroups.count();
- for (i = 0; i < count; i++)
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); )
{
- if (mViewerPartGroups[i]->getRegion() == regionp)
+ group_list_t::iterator iter = i++;
+
+ if ((*iter)->getRegion() == regionp)
{
- delete mViewerPartGroups[i];
- mViewerPartGroups.remove(i);
- i--;
- count--;
+ i = mViewerPartGroups.erase(iter);
}
}
}
void LLViewerPartSim::cleanMutedParticles(const LLUUID& task_id)
{
- S32 i;
- S32 count = mViewerPartSources.count();
- for (i = 0; i < count; ++i)
+ LLMemType mt(LLMemType::MTYPE_PARTICLES);
+ for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); )
{
- if (mViewerPartSources[i]->getOwnerUUID() == task_id)
+ source_list_t::iterator iter = i++;
+
+ if ((*iter)->getOwnerUUID() == task_id)
{
- mViewerPartSources.remove(i);
- i--;
- count--;
+ i = mViewerPartSources.erase(iter);
}
}
}