📄 particle.cpp
字号:
ParticleSystem::initParticle(p, particleIndex);
float x= random.randRange(-radius, radius);
float y= random.randRange(-radius, radius);
p->color= color;
p->energy= 10000;
p->pos= Vec3f(pos.x+x, pos.y, pos.z+y);
p->lastPos= p->pos;
p->speed= Vec3f(0.0f, -speed, 0.0f) + windSpeed;
p->speed.x+= random.randRange(-0.005f, 0.005f);
p->speed.y+= random.randRange(-0.005f, 0.005f);
}
bool SnowParticleSystem::deathTest(Particle *p){
return p->pos.y<0;
}
void SnowParticleSystem::setRadius(float radius){
this->radius= radius;
}
void SnowParticleSystem::setWind(float windAngle, float windSpeed){
this->windSpeed.x= sinf(degToRad(windAngle))*windSpeed;
this->windSpeed.y= 0.0f;
this->windSpeed.z= cosf(degToRad(windAngle))*windSpeed;
}
// ===========================================================================
// AttackParticleSystem
// ===========================================================================
AttackParticleSystem::AttackParticleSystem(int particleCount): ParticleSystem(particleCount){
model= NULL;
primitive= pQuad;
offset= Vec3f(0.0f);
gravity= 0.0f;
direction= Vec3f(1.0f, 0.0f, 0.0f);
}
void AttackParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
if(active){
if(model!=NULL){
pr->renderSingleModel(this, mr);
}
switch(primitive){
case pQuad:
pr->renderSystem(this);
break;
case pLine:
pr->renderSystemLine(this);
break;
default:
assert(false);
}
}
}
AttackParticleSystem::Primitive AttackParticleSystem::strToPrimitive(const string &str){
if(str=="quad"){
return pQuad;
}
else if(str=="line"){
return pLine;
}
else{
throw "Unknown particle primitive: " + str;
}
}
// ===========================================================================
// ProjectileParticleSystem
// ===========================================================================
ProjectileParticleSystem::ProjectileParticleSystem(int particleCount): AttackParticleSystem(particleCount){
setEmissionRate(20);
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.5f));
setMaxParticleEnergy(100);
setVarParticleEnergy(50);
setParticleSize(0.4f);
setSpeed(0.14f);
trajectory= tLinear;
trajectorySpeed= 1.0f;
trajectoryScale= 1.0f;
trajectoryFrequency = 1.0f;
nextParticleSystem= NULL;
}
ProjectileParticleSystem::~ProjectileParticleSystem(){
if(nextParticleSystem!=NULL){
nextParticleSystem->prevParticleSystem= NULL;
}
}
void ProjectileParticleSystem::link(SplashParticleSystem *particleSystem){
nextParticleSystem= particleSystem;
nextParticleSystem->setState(sPause);
nextParticleSystem->prevParticleSystem= this;
}
void ProjectileParticleSystem::update(){
if(state==sPlay){
lastPos= pos;
flatPos+= zVector * trajectorySpeed;
Vec3f targetVector= endPos - startPos;
Vec3f currentVector= flatPos - startPos;
// ratio
float t= clamp(currentVector.length() / targetVector.length(), 0.0f, 1.0f);
// trajectory
switch(trajectory){
case tLinear:
{
pos= flatPos;
}
break;
case tParabolic:
{
float scaledT= 2.0f * (t-0.5f);
float paraboleY= (1.0f-scaledT*scaledT) * trajectoryScale;
pos = flatPos;
pos.y+= paraboleY;
}
break;
case tSpiral:
{
pos= flatPos;
pos+= xVector * cos(t*trajectoryFrequency*targetVector.length())*trajectoryScale;
pos+= yVector * sin(t*trajectoryFrequency*targetVector.length())*trajectoryScale;
}
break;
default:
assert(false);
}
direction= pos - lastPos;
direction.normalize();
//arrive destination
if( flatPos.dist(endPos)<0.5f ){
state= sFade;
model= NULL;
if(particleObserver!=NULL){
particleObserver->update(this);
}
if(nextParticleSystem!=NULL){
nextParticleSystem->setState(sPlay);
nextParticleSystem->setPos(endPos);
}
}
}
ParticleSystem::update();
}
void ProjectileParticleSystem::initParticle(Particle *p, int particleIndex){
ParticleSystem::initParticle(p, particleIndex);
float t= static_cast<float>(particleIndex)/emissionRate;
p->pos= pos + (lastPos - pos) * t;
p->lastPos= lastPos;
p->speed= Vec3f(random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f)) * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
updateParticle(p);
}
void ProjectileParticleSystem::updateParticle(Particle *p){
float energyRatio= clamp(static_cast<float>(p->energy)/maxParticleEnergy, 0.f, 1.f);
p->lastPos+= p->speed;
p->pos+= p->speed;
p->speed+= p->accel;
p->color = color * energyRatio + colorNoEnergy * (1.0f-energyRatio);
p->size = particleSize * energyRatio + sizeNoEnergy * (1.0f-energyRatio);
p->energy--;
}
void ProjectileParticleSystem::setPath(Vec3f startPos, Vec3f endPos){
//compute axis
zVector= endPos - startPos;
zVector.normalize();
yVector= Vec3f(0.0f, 1.0f, 0.0f);
xVector= zVector.cross(yVector);
//apply offset
startPos+= xVector * offset.x;
startPos+= yVector * offset.y;
startPos+= zVector * offset.z;
pos= startPos;
lastPos= startPos;
flatPos= startPos;
//recompute axis
zVector= endPos - startPos;
zVector.normalize();
yVector= Vec3f(0.0f, 1.0f, 0.0f);
xVector= zVector.cross(yVector);
// set members
this->startPos= startPos;
this->endPos= endPos;
}
ProjectileParticleSystem::Trajectory ProjectileParticleSystem::strToTrajectory(const string &str){
if(str=="linear"){
return tLinear;
}
else if(str=="parabolic"){
return tParabolic;
}
else if(str=="spiral"){
return tSpiral;
}
else{
throw "Unknown particle system trajectory: " + str;
}
}
// ===========================================================================
// SplashParticleSystem
// ===========================================================================
SplashParticleSystem::SplashParticleSystem(int particleCount): AttackParticleSystem(particleCount){
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.8f));
setMaxParticleEnergy(100);
setVarParticleEnergy(50);
setParticleSize(1.0f);
setSpeed(0.003f);
prevParticleSystem= NULL;
emissionRateFade= 1;
verticalSpreadA= 1.0f;
verticalSpreadB= 0.0f;
horizontalSpreadA= 1.0f;
horizontalSpreadB= 0.0f;
}
SplashParticleSystem::~SplashParticleSystem(){
if(prevParticleSystem!=NULL){
prevParticleSystem->nextParticleSystem= NULL;
}
}
void SplashParticleSystem::update(){
ParticleSystem::update();
if(state!=sPause){
emissionRate-= emissionRateFade;
}
}
void SplashParticleSystem::initParticle(Particle *p, int particleIndex){
p->pos= pos;
p->lastPos= p->pos;
p->energy= maxParticleEnergy;
p->size= particleSize;
p->color= color;
p->speed= Vec3f(
horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB,
verticalSpreadA * random.randRange(-1.0f, 1.0f) + verticalSpreadB,
horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB);
p->speed.normalize();
p->speed= p->speed * speed;
p->accel= Vec3f(0.0f, -gravity, 0.0f);
}
void SplashParticleSystem::updateParticle(Particle *p){
float energyRatio= clamp(static_cast<float>(p->energy)/maxParticleEnergy, 0.f, 1.f);
p->lastPos= p->pos;
p->pos= p->pos + p->speed;
p->speed= p->speed + p->accel;
p->energy--;
p->color = color * energyRatio + colorNoEnergy * (1.0f-energyRatio);
p->size = particleSize * energyRatio + sizeNoEnergy * (1.0f-energyRatio);
}
// ===========================================================================
// ParticleManager
// ===========================================================================
ParticleManager::~ParticleManager(){
end();
}
void ParticleManager::render(ParticleRenderer *pr, ModelRenderer *mr) const{
list<ParticleSystem*>::const_iterator it;
for (it=particleSystems.begin(); it!=particleSystems.end(); it++){
if((*it)->getVisible()){
(*it)->render(pr, mr);
}
}
}
void ParticleManager::update(){
list<ParticleSystem*>::iterator it;
for (it=particleSystems.begin(); it!=particleSystems.end(); it++){
(*it)->update();
if((*it)->isEmpty()){
delete *it;
*it= NULL;
}
}
particleSystems.remove(NULL);
}
void ParticleManager::manage(ParticleSystem *ps){
particleSystems.push_back(ps);
}
void ParticleManager::end(){
while(!particleSystems.empty()){
delete particleSystems.front();
particleSystems.pop_front();
}
}
}}//end namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -