?? particle_system.h
字號:
// Particle_system.h: interface for the Particle_system class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_PARTICLE_SYSTEM_H__B8CA2EC3_7214_11D8_8A6F_AB83B4D90309__INCLUDED_)
#define AFX_PARTICLE_SYSTEM_H__B8CA2EC3_7214_11D8_8A6F_AB83B4D90309__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "init.h"
#include "texture.h"
#include <vector>
using namespace std;
class palette
{
public:
vector<vec> colors;
vec get(float t)
{
if(colors.size()<2)
{
if(colors.size()==1)return colors[0];
else return vec(1,1,1);
}
int index = (int)floor( t*(float)(colors.size()-1) );
if(index>=colors.size()-1)return colors[colors.size()-1];
if(index<=0)return colors[0];
float d = t*(float)(colors.size()-1) - (float)index;
return (1-d)*colors[index] + d*colors[index+1];
}
void add(vec color){ colors.push_back(color); }
int load(char* filename)
{
texture a;
vec col;
if(!a.imageLoad(filename))return 0;
a.BGRtoRGB(a.im);
for(int x=0; x<a.im.sizeX; x++)
{
col.x = (float)a.im.data[ (0*a.im.sizeX+x)*a.im.planes + 0]/255.f;
col.y = (float)a.im.data[ (0*a.im.sizeX+x)*a.im.planes + 1]/255.f;
col.z = (float)a.im.data[ (0*a.im.sizeX+x)*a.im.planes + 2]/255.f;
colors.push_back(col);
}
}
void set_fire()
{
colors.resize(12,vec(0,0,0));
for(int i=0; i<4; i++) // from humus, Particles.h, COLOR_SCHEME_FIRE
{
colors[i ].set(i / 4.0f, 0, 0);
colors[i + 4].set(1, i / 4.0f, 0);
colors[i + 8].set((3 - i) / 3.0f,(3 - i) / 3.0f, 1);
}
swap();
}
void set_ice()
{
colors.resize(12,vec(0,0,0));
for (int i = 0; i < 6; i++) // from humus, Particles.h, COLOR_SCHEME_ICE
{
colors[i ] = vec(0,0,i / 6.0f);
colors[i + 6] = vec(i / 5.0f,1,1);
}
swap();
}
void set_smoke()
{
colors.resize(12,vec(0,0,0));
for (int i = 0; i < 12; i++) // from humus, Particles.h, COLOR_SCHEME_SMOKE
{
float f = i / 44.0f;
colors[i] = vec(f,f,f);
}
swap();
}
void set_rainbow()
{
colors.resize(12,vec(0,0,0));
colors[0] = vec(0, 0, 0); // from humus, Particles.h, COLOR_SCHEME_RAINBOW
colors[1] = vec(0, 0, 0.25f);
colors[2] = vec(0, 0, 0.5f);
colors[3] = vec(0, 0, 1);
colors[4] = vec(0, 0.5f,1);
colors[5] = vec(0, 1, 1);
colors[6] = vec(0, 1, 0.5f);
colors[7] = vec(0, 1, 0);
colors[8] = vec(0.5f,1, 0);
colors[9] = vec(1, 1, 0);
colors[10] = vec(1, 0.5f,0);
colors[11] = vec(1, 0, 0);
swap();
}
void swap()
{
for(int i=0; i<colors.size()/2; i++)
{
vec temp = colors[i];
colors[i] = colors[colors.size()-1-i];
colors[colors.size()-1-i] = temp;
}
}
};
class Function
{
public:
vector<float> values;
float get(float t)
{
if(values.size()<2)
{
if(values.size()==1)return values[0];
else return 1.f;
}
int index = (int)floor( t*(float)(values.size()-1) );
if(index>=values.size()-1)return values[values.size()-1];
if(index<=0)return values[0];
float d = t*(float)(values.size()-1) - (float)index;
return (1-d)*values[index] + d*values[index+1];
}
void add(float value){ values.push_back(value); }
};
struct z_Particle
{
vec pos; // position
vec vel; // velocity
vec grav; // gravitation
Function *r; // radius = half of size
vec color;
palette *pal_color; // if pal_color == NULL, uses variable color
vec getColor(){ return pal_color->get(t); }
float get_r(){ return r->get(t); }
float lifetime; // age of particle in second
float t; // [0,1], if > 1 => kill particle
};
#define frand() ((float)rand()/(float)RAND_MAX) // [ 0, 1]
#define frand2() (2.f*(float)rand()/(float)RAND_MAX-1.f) // [-1, 1]
class Emiter
{
public:
virtual int Emit_next_frame(float timeframe) = 0; // call Emit_test ?
virtual int Emit_test() = 0; // emit another particle ?
virtual z_Particle Emit() = 0; // generate one particle
};
class Emiter_stream : public Emiter
{
public:
int max_particles;
vec pos; // position
vec vel; // velocity
vec grav; // gravitation
Function *r; // radius = half of size
float lifetime; // age of particle in second
float period_of_effect;
float time;
float max_time; // must by max_time < period_of_effect
vec color_par; // particle color
palette *color_emiter; // color emiter
float time_to_add_particle; // update in each frame
float angle_of_scatter; // (sk) uhol rozptylu
float angle_of_cut_out; // must by < angle_of_scatter
float period_of_color_cycle;
float t_of_color_cycle;
int Emit_next_frame(float timeframe)
{
time += timeframe;
if(time>period_of_effect)time=0;
if(time>max_time)return 0;
time_to_add_particle -= timeframe;
t_of_color_cycle += timeframe/period_of_color_cycle;
if(t_of_color_cycle>1.f)t_of_color_cycle=0;
color_par = color_emiter->get(t_of_color_cycle+0.003*frand());
// vel.RotZ(180.f*timeframe);
// grav = -0.1f*vel;
return 1;
}
int Emit_test()
{
if(time_to_add_particle<0)return 1;
else return 0;
}
z_Particle Emit()
{
z_Particle a;
/* a.pos.set(0,0,frand2());
a.vel.set(0,0.6f,0);
static rot=0;
rot+=31;
a.vel.RotZ(rot);
if(rot>360)rot-=360.f;
a.pos+=0.3f*a.vel;*/
// a.grav.set(0.3f,-0.5f,0.f);
// a.vel.set(0.2f*frand2(),frand()+0.8f,0.2f*frand2());
// a.grav.set(0.6f*frand2(),-1.0f*frand2(),0.6f*frand2());
// a.grav.set(0.06f*frand2(),1.0f*frand2(),0.06f*frand2());
a.pos = pos;
a.vel = vel;
vec orthogonal(a.vel);
orthogonal.RotZ(23.f);
// orthogonal.RotY(23.f);
orthogonal = CROSS(a.vel,orthogonal);
float rnd = frand();
// rnd *= rnd;
a.vel.ArbitraryRotate(angle_of_cut_out+(angle_of_scatter-angle_of_cut_out)*rnd,orthogonal);
a.vel.ArbitraryRotate(360.f*frand(), vel);
a.grav = grav;
a.r = r;
a.pal_color = color_emiter;
// a.color = color_par;
a.lifetime = lifetime-0.2f*lifetime*frand();
a.t = 0;
time_to_add_particle += lifetime/(float)max_particles;
return a;
}
};
class Emiter_sphere : public Emiter
{
public:
int max_particles;
vec pos; // position
vec vel; // velocity
vec grav; // gravitation
Function *r_rocket; // radius = half of size
Function *r_sphere; // radius = half of size
float lifetime_rocket; // age of particle in second
float lifetime_sphere; // age of particle in second
float period_of_effect; // period_of_effect > lifetime_rocket+lifetime_sphere
vec color_par; // particle color
// palette *color_emiter; // color emiter
float angle_of_scatter; // (sk) uhol rozptylu
float times;
int gen;
private:
vec pos_rocket;
vec vel_rocket;
float gen_piece_time; // falling pieces
public:
int Emit_next_frame(float timeframe)
{
times += timeframe;
if(gen==-1)
{
times=0;
pos_rocket=pos;
vel_rocket=vel;
gen_piece_time=0;
return 1; // will generate rocket
}
else if(times<lifetime_rocket)
// generate small piece
{
vel_rocket += timeframe*grav;
pos_rocket += timeframe*vel_rocket;
gen_piece_time -= timeframe;
if(gen_piece_time<0)
return 1;
else
return 0;
}
else if(gen<max_particles)
{
return 1; // will generate sphere
}
else if(times>=period_of_effect)
{
gen=-1;
times=0;
pos_rocket=pos;
vel_rocket=vel;
gen_piece_time = 0;
return 1;
}
return 0;
}
int Emit_test()
{
if(gen==-1)return 1;
if(times>=lifetime_rocket && gen<max_particles)return 1;
if(gen_piece_time<0)return 1;
return 0;
}
z_Particle Emit()
{
z_Particle a;
if(gen==-1)
{
a.pos = pos;
a.vel = vel;
a.grav = grav;
a.r = r_rocket;
a.color.set(frand(),frand(),frand());;
color_par = a.color;
a.pal_color = NULL;
a.lifetime = lifetime_rocket;
a.t = 0;
gen++;
}
else if(gen_piece_time<0)
{
a.pos = pos_rocket;
a.vel = 0.5f*vel_rocket;
a.grav = grav;
a.r = r_sphere;
a.color = color_par;
a.pal_color = NULL;
a.lifetime = 0.2f*lifetime_rocket;
a.t = 0;
gen_piece_time += 0.01f;
}
else
{
a.pos = pos_rocket;
a.vel.set(frand2(),frand2(),frand2());
a.vel.Normalize();
a.grav = grav;
a.r = r_sphere;
a.color = color_par;
a.pal_color = NULL;
a.lifetime = lifetime_sphere*(0.4f+0.6f*frand());
a.t = 0;
gen++;
}
return a;
}
};
class Particle_system
{
public:
void Emit(float timeframe);
void Update(float timeframe);
void Render(vec vr, vec vu);
palette color[10];
Function func[5];
vector<z_Particle> par;
vector<Emiter*> emiter;
Particle_system();
virtual ~Particle_system();
};
#endif // !defined(AFX_PARTICLE_SYSTEM_H__B8CA2EC3_7214_11D8_8A6F_AB83B4D90309__INCLUDED_)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -