diff options
Diffstat (limited to '')
| -rw-r--r-- | servers/visual/particle_system_sw.cpp | 312 |
1 files changed, 142 insertions, 170 deletions
diff --git a/servers/visual/particle_system_sw.cpp b/servers/visual/particle_system_sw.cpp index 9f26589ff..15809f51a 100644 --- a/servers/visual/particle_system_sw.cpp +++ b/servers/visual/particle_system_sw.cpp @@ -29,53 +29,48 @@ #include "particle_system_sw.h" #include "sort.h" - ParticleSystemSW::ParticleSystemSW() { - amount=8; - emitting=true; + amount = 8; + emitting = true; - for (int i=0;i<VS::PARTICLE_VAR_MAX;i++) { - particle_randomness[i]=0.0; + for (int i = 0; i < VS::PARTICLE_VAR_MAX; i++) { + particle_randomness[i] = 0.0; } - particle_vars[VS::PARTICLE_LIFETIME]=2.0;// - particle_vars[VS::PARTICLE_SPREAD]=0.2;// - particle_vars[VS::PARTICLE_GRAVITY]=9.8;// - particle_vars[VS::PARTICLE_LINEAR_VELOCITY]=0.2;// - particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]=0.0;// - particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]=1.0;// - particle_vars[VS::PARTICLE_DAMPING]=0.0;// - particle_vars[VS::PARTICLE_INITIAL_SIZE]=1.0; - particle_vars[VS::PARTICLE_FINAL_SIZE]=0.8; - particle_vars[VS::PARTICLE_HEIGHT]=1; - particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]=1; + particle_vars[VS::PARTICLE_LIFETIME] = 2.0; // + particle_vars[VS::PARTICLE_SPREAD] = 0.2; // + particle_vars[VS::PARTICLE_GRAVITY] = 9.8; // + particle_vars[VS::PARTICLE_LINEAR_VELOCITY] = 0.2; // + particle_vars[VS::PARTICLE_ANGULAR_VELOCITY] = 0.0; // + particle_vars[VS::PARTICLE_LINEAR_ACCELERATION] = 0.0; // + particle_vars[VS::PARTICLE_RADIAL_ACCELERATION] = 0.0; // + particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION] = 1.0; // + particle_vars[VS::PARTICLE_DAMPING] = 0.0; // + particle_vars[VS::PARTICLE_INITIAL_SIZE] = 1.0; + particle_vars[VS::PARTICLE_FINAL_SIZE] = 0.8; + particle_vars[VS::PARTICLE_HEIGHT] = 1; + particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE] = 1; - height_from_velocity=false; - local_coordinates=false; + height_from_velocity = false; + local_coordinates = false; - particle_vars[VS::PARTICLE_INITIAL_ANGLE]=0.0;// + particle_vars[VS::PARTICLE_INITIAL_ANGLE] = 0.0; // - gravity_normal=Vector3(0,-1.0,0); + gravity_normal = Vector3(0, -1.0, 0); //emission_half_extents=Vector3(0.1,0.1,0.1); - emission_half_extents=Vector3(1,1,1); - color_phase_count=0; - color_phases[0].pos=0.0; - color_phases[0].color=Color(1.0,0.0,0.0); - visibility_aabb=AABB(Vector3(-64,-64,-64),Vector3(128,128,128)); - - attractor_count=0; + emission_half_extents = Vector3(1, 1, 1); + color_phase_count = 0; + color_phases[0].pos = 0.0; + color_phases[0].color = Color(1.0, 0.0, 0.0); + visibility_aabb = AABB(Vector3(-64, -64, -64), Vector3(128, 128, 128)); + attractor_count = 0; } - -ParticleSystemSW::~ParticleSystemSW() -{ +ParticleSystemSW::~ParticleSystemSW() { } - #define DEFAULT_SEED 1234567 _FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) { @@ -90,8 +85,8 @@ _FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) { s += 2147483647; (*seed) = s; - float v=((float)((*seed) & 0xFFFFF))/(float)0xFFFFF; - v=v*2.0-1.0; + float v = ((float)((*seed) & 0xFFFFF)) / (float)0xFFFFF; + v = v * 2.0 - 1.0; return v; } @@ -110,112 +105,108 @@ _FORCE_INLINE_ static uint32_t _irand_from_seed(uint32_t *seed) { return s; } -void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time) { +void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system, const Transform &p_transform, float p_time) { - valid=false; - if (p_system->amount<=0) { - ERR_EXPLAIN("Invalid amount of particles: "+itos(p_system->amount)); - ERR_FAIL_COND(p_system->amount<=0); + valid = false; + if (p_system->amount <= 0) { + ERR_EXPLAIN("Invalid amount of particles: " + itos(p_system->amount)); + ERR_FAIL_COND(p_system->amount <= 0); } - if (p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS) { + if (p_system->attractor_count < 0 || p_system->attractor_count > VS::MAX_PARTICLE_ATTRACTORS) { ERR_EXPLAIN("Invalid amount of particle attractors."); - ERR_FAIL_COND(p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS); + ERR_FAIL_COND(p_system->attractor_count < 0 || p_system->attractor_count > VS::MAX_PARTICLE_ATTRACTORS); } float lifetime = p_system->particle_vars[VS::PARTICLE_LIFETIME]; - if (lifetime<CMP_EPSILON) { + if (lifetime < CMP_EPSILON) { ERR_EXPLAIN("Particle system lifetime too small."); - ERR_FAIL_COND(lifetime<CMP_EPSILON); + ERR_FAIL_COND(lifetime < CMP_EPSILON); } - valid=true; - int particle_count=MIN(p_system->amount,ParticleSystemSW::MAX_PARTICLES);; - + valid = true; + int particle_count = MIN(p_system->amount, ParticleSystemSW::MAX_PARTICLES); + ; int emission_point_count = p_system->emission_points.size(); DVector<Vector3>::Read r; if (emission_point_count) - r=p_system->emission_points.read(); + r = p_system->emission_points.read(); - if (particle_count!=particle_data.size()) { + if (particle_count != particle_data.size()) { //clear the whole system if particle amount changed particle_data.clear(); particle_data.resize(p_system->amount); - particle_system_time=0; + particle_system_time = 0; } - float next_time = particle_system_time+p_time; + float next_time = particle_system_time + p_time; if (next_time > lifetime) - next_time=Math::fmod(next_time,lifetime); - + next_time = Math::fmod(next_time, lifetime); - ParticleData *pdata=&particle_data[0]; + ParticleData *pdata = &particle_data[0]; Vector3 attractor_positions[VS::MAX_PARTICLE_ATTRACTORS]; - for(int i=0;i<p_system->attractor_count;i++) { + for (int i = 0; i < p_system->attractor_count; i++) { - attractor_positions[i]=p_transform.xform(p_system->attractors[i].pos); + attractor_positions[i] = p_transform.xform(p_system->attractors[i].pos); } + for (int i = 0; i < particle_count; i++) { - for(int i=0;i<particle_count;i++) { - - ParticleData &p=pdata[i]; + ParticleData &p = pdata[i]; float restart_time = (i * lifetime / p_system->amount); - bool restart=false; + bool restart = false; - if ( next_time < particle_system_time ) { + if (next_time < particle_system_time) { - if (restart_time > particle_system_time || restart_time < next_time ) - restart=true; + if (restart_time > particle_system_time || restart_time < next_time) + restart = true; - } else if (restart_time > particle_system_time && restart_time < next_time ) { - restart=true; + } else if (restart_time > particle_system_time && restart_time < next_time) { + restart = true; } if (restart) { - if (p_system->emitting) { - if (emission_point_count==0) { //use AABB + if (emission_point_count == 0) { //use AABB if (p_system->local_coordinates) - p.pos = p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ); + p.pos = p_system->emission_half_extents * Vector3(_rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed)); else - p.pos = p_transform.xform( p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ) ); + p.pos = p_transform.xform(p_system->emission_half_extents * Vector3(_rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed))); } else { //use preset positions if (p_system->local_coordinates) - p.pos = r[_irand_from_seed(&rand_seed)%emission_point_count]; + p.pos = r[_irand_from_seed(&rand_seed) % emission_point_count]; else - p.pos = p_transform.xform( r[_irand_from_seed(&rand_seed)%emission_point_count] ); + p.pos = p_transform.xform(r[_irand_from_seed(&rand_seed) % emission_point_count]); } + float angle1 = _rand_from_seed(&rand_seed) * p_system->particle_vars[VS::PARTICLE_SPREAD] * Math_PI; + float angle2 = _rand_from_seed(&rand_seed) * 20.0 * Math_PI; // make it more random like - float angle1 = _rand_from_seed(&rand_seed)*p_system->particle_vars[VS::PARTICLE_SPREAD]*Math_PI; - float angle2 = _rand_from_seed(&rand_seed)*20.0*Math_PI; // make it more random like - - Vector3 rot_xz=Vector3( Math::sin(angle1), 0.0, Math::cos(angle1) ); - Vector3 rot = Vector3( Math::cos(angle2)*rot_xz.x,Math::sin(angle2)*rot_xz.x, rot_xz.z); + Vector3 rot_xz = Vector3(Math::sin(angle1), 0.0, Math::cos(angle1)); + Vector3 rot = Vector3(Math::cos(angle2) * rot_xz.x, Math::sin(angle2) * rot_xz.x, rot_xz.z); - p.vel=(rot*p_system->particle_vars[VS::PARTICLE_LINEAR_VELOCITY]+rot*p_system->particle_randomness[VS::PARTICLE_LINEAR_VELOCITY]*_rand_from_seed(&rand_seed)); + p.vel = (rot * p_system->particle_vars[VS::PARTICLE_LINEAR_VELOCITY] + rot * p_system->particle_randomness[VS::PARTICLE_LINEAR_VELOCITY] * _rand_from_seed(&rand_seed)); if (!p_system->local_coordinates) - p.vel=p_transform.basis.xform( p.vel ); + p.vel = p_transform.basis.xform(p.vel); - p.vel+=p_system->emission_base_velocity; + p.vel += p_system->emission_base_velocity; - p.rot=p_system->particle_vars[VS::PARTICLE_INITIAL_ANGLE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_ANGLE]*_rand_from_seed(&rand_seed); - p.active=true; - for(int r=0;r<PARTICLE_RANDOM_NUMBERS;r++) - p.random[r]=_rand_from_seed(&rand_seed); + p.rot = p_system->particle_vars[VS::PARTICLE_INITIAL_ANGLE] + p_system->particle_randomness[VS::PARTICLE_INITIAL_ANGLE] * _rand_from_seed(&rand_seed); + p.active = true; + for (int r = 0; r < PARTICLE_RANDOM_NUMBERS; r++) + p.random[r] = _rand_from_seed(&rand_seed); } else { - p.pos=Vector3(); - p.rot=0; - p.vel=Vector3(); - p.active=false; + p.pos = Vector3(); + p.rot = 0; + p.vel = Vector3(); + p.active = false; } } else { @@ -225,110 +216,100 @@ void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system,const Tra Vector3 force; //apply gravity - force=p_system->gravity_normal * (p_system->particle_vars[VS::PARTICLE_GRAVITY]+(p_system->particle_randomness[VS::PARTICLE_GRAVITY]*p.random[0])); + force = p_system->gravity_normal * (p_system->particle_vars[VS::PARTICLE_GRAVITY] + (p_system->particle_randomness[VS::PARTICLE_GRAVITY] * p.random[0])); //apply linear acceleration - force+=p.vel.normalized() * (p_system->particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_LINEAR_ACCELERATION]*p.random[1]); + force += p.vel.normalized() * (p_system->particle_vars[VS::PARTICLE_LINEAR_ACCELERATION] + p_system->particle_randomness[VS::PARTICLE_LINEAR_ACCELERATION] * p.random[1]); //apply radial acceleration Vector3 org; if (!p_system->local_coordinates) - org=p_transform.origin; - force+=(p.pos-org).normalized() * (p_system->particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_RADIAL_ACCELERATION]*p.random[2]); + org = p_transform.origin; + force += (p.pos - org).normalized() * (p_system->particle_vars[VS::PARTICLE_RADIAL_ACCELERATION] + p_system->particle_randomness[VS::PARTICLE_RADIAL_ACCELERATION] * p.random[2]); //apply tangential acceleration - force+=(p.pos-org).cross(p_system->gravity_normal).normalized() * (p_system->particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_TANGENTIAL_ACCELERATION]*p.random[3]); + force += (p.pos - org).cross(p_system->gravity_normal).normalized() * (p_system->particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION] + p_system->particle_randomness[VS::PARTICLE_TANGENTIAL_ACCELERATION] * p.random[3]); //apply attractor forces - for(int a=0;a<p_system->attractor_count;a++) { + for (int a = 0; a < p_system->attractor_count; a++) { - force+=(p.pos-attractor_positions[a]).normalized() * p_system->attractors[a].force; + force += (p.pos - attractor_positions[a]).normalized() * p_system->attractors[a].force; } - - p.vel+=force * p_time; + p.vel += force * p_time; if (p_system->particle_vars[VS::PARTICLE_DAMPING]) { float v = p.vel.length(); float damp = p_system->particle_vars[VS::PARTICLE_DAMPING] + p_system->particle_vars[VS::PARTICLE_DAMPING] * p_system->particle_randomness[VS::PARTICLE_DAMPING]; v -= damp * p_time; - if (v<0) { - p.vel=Vector3(); + if (v < 0) { + p.vel = Vector3(); } else { - p.vel=p.vel.normalized() * v; + p.vel = p.vel.normalized() * v; } - } - p.rot+=(p_system->particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]+p_system->particle_randomness[VS::PARTICLE_ANGULAR_VELOCITY]*p.random[4]) *p_time; - p.pos+=p.vel * p_time; + p.rot += (p_system->particle_vars[VS::PARTICLE_ANGULAR_VELOCITY] + p_system->particle_randomness[VS::PARTICLE_ANGULAR_VELOCITY] * p.random[4]) * p_time; + p.pos += p.vel * p_time; } } - particle_system_time=Math::fmod( particle_system_time+p_time, lifetime ); - - + particle_system_time = Math::fmod(particle_system_time + p_time, lifetime); } ParticleSystemProcessSW::ParticleSystemProcessSW() { - particle_system_time=0; - rand_seed=1234567; - valid=false; + particle_system_time = 0; + rand_seed = 1234567; + valid = false; } - struct _ParticleSorterSW { - - _FORCE_INLINE_ bool operator()(const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_a,const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_b) const { + _FORCE_INLINE_ bool operator()(const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_a, const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_b) const { return p_a->d > p_b->d; // draw from further away to closest } }; -void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform) { +void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system, const ParticleSystemProcessSW *p_process, const Transform &p_system_transform, const Transform &p_camera_transform) { ERR_FAIL_COND(p_process->particle_data.size() != p_system->amount); - ERR_FAIL_COND(p_system->amount<=0 || p_system->amount>=ParticleSystemSW::MAX_PARTICLES); + ERR_FAIL_COND(p_system->amount <= 0 || p_system->amount >= ParticleSystemSW::MAX_PARTICLES); - const ParticleSystemProcessSW::ParticleData *pdata=&p_process->particle_data[0]; - float time_pos=p_process->particle_system_time/p_system->particle_vars[VS::PARTICLE_LIFETIME]; + const ParticleSystemProcessSW::ParticleData *pdata = &p_process->particle_data[0]; + float time_pos = p_process->particle_system_time / p_system->particle_vars[VS::PARTICLE_LIFETIME]; ParticleSystemSW::ColorPhase cphase[VS::MAX_PARTICLE_COLOR_PHASES]; - float last=-1; - int col_count=0; + float last = -1; + int col_count = 0; - for(int i=0;i<p_system->color_phase_count;i++) { + for (int i = 0; i < p_system->color_phase_count; i++) { - if (p_system->color_phases[i].pos<=last) + if (p_system->color_phases[i].pos <= last) break; - cphase[i]=p_system->color_phases[i]; + cphase[i] = p_system->color_phases[i]; col_count++; } - - - - Vector3 camera_z_axis = p_camera_transform.basis.get_axis(2); - for(int i=0;i<p_system->amount;i++) { + for (int i = 0; i < p_system->amount; i++) { - ParticleDrawInfo &pdi=draw_info[i]; - pdi.data=&pdata[i]; - pdi.transform.origin=pdi.data->pos; + ParticleDrawInfo &pdi = draw_info[i]; + pdi.data = &pdata[i]; + pdi.transform.origin = pdi.data->pos; if (p_system->local_coordinates) - pdi.transform.origin=p_system_transform.xform(pdi.transform.origin); + pdi.transform.origin = p_system_transform.xform(pdi.transform.origin); - pdi.d=-camera_z_axis.dot(pdi.transform.origin); + pdi.d = -camera_z_axis.dot(pdi.transform.origin); // adjust particle size, color and rotation float time = ((float)i / p_system->amount); - if (time<time_pos) - time=time_pos-time; + if (time < time_pos) + time = time_pos - time; else - time=(1.0-time)+time_pos; + time = (1.0 - time) + time_pos; - Vector3 up=p_camera_transform.basis.get_axis(1); // up determines the rotation - float up_scale=1.0; + Vector3 up = p_camera_transform.basis.get_axis(1); // up determines the rotation + float up_scale = 1.0; if (p_system->height_from_velocity) { @@ -336,47 +317,43 @@ void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const Pa Vector3 cam_z = camera_z_axis.normalized(); float vc = Math::abs(veld.normalized().dot(cam_z)); - if (vc<(1.0-CMP_EPSILON)) { - up = Plane(cam_z,0).project(veld).normalized(); - float h = p_system->particle_vars[VS::PARTICLE_HEIGHT]+p_system->particle_randomness[VS::PARTICLE_HEIGHT]*pdi.data->random[7]; + if (vc < (1.0 - CMP_EPSILON)) { + up = Plane(cam_z, 0).project(veld).normalized(); + float h = p_system->particle_vars[VS::PARTICLE_HEIGHT] + p_system->particle_randomness[VS::PARTICLE_HEIGHT] * pdi.data->random[7]; float velh = veld.length(); - h+=velh*(p_system->particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]+p_system->particle_randomness[VS::PARTICLE_HEIGHT_SPEED_SCALE]*pdi.data->random[7]); - + h += velh * (p_system->particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE] + p_system->particle_randomness[VS::PARTICLE_HEIGHT_SPEED_SCALE] * pdi.data->random[7]); - up_scale=Math::lerp(1.0,h,(1.0-vc)); + up_scale = Math::lerp(1.0, h, (1.0 - vc)); } } else if (pdi.data->rot) { - up.rotate(camera_z_axis,pdi.data->rot); + up.rotate(camera_z_axis, pdi.data->rot); } { // matrix - Vector3 v_z = (p_camera_transform.origin-pdi.transform.origin).normalized(); -// Vector3 v_z = (p_camera_transform.origin-pdi.data->pos).normalized(); + Vector3 v_z = (p_camera_transform.origin - pdi.transform.origin).normalized(); + // Vector3 v_z = (p_camera_transform.origin-pdi.data->pos).normalized(); Vector3 v_y = up; Vector3 v_x = v_y.cross(v_z); v_y = v_z.cross(v_x); v_x.normalize(); v_y.normalize(); - float initial_scale, final_scale; - initial_scale = p_system->particle_vars[VS::PARTICLE_INITIAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_SIZE]*pdi.data->random[5]; - final_scale = p_system->particle_vars[VS::PARTICLE_FINAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_FINAL_SIZE]*pdi.data->random[6]; + initial_scale = p_system->particle_vars[VS::PARTICLE_INITIAL_SIZE] + p_system->particle_randomness[VS::PARTICLE_INITIAL_SIZE] * pdi.data->random[5]; + final_scale = p_system->particle_vars[VS::PARTICLE_FINAL_SIZE] + p_system->particle_randomness[VS::PARTICLE_FINAL_SIZE] * pdi.data->random[6]; float scale = initial_scale + time * (final_scale - initial_scale); - pdi.transform.basis.set_axis(0,v_x * scale); - pdi.transform.basis.set_axis(1,v_y * scale * up_scale); - pdi.transform.basis.set_axis(2,v_z * scale); + pdi.transform.basis.set_axis(0, v_x * scale); + pdi.transform.basis.set_axis(1, v_y * scale * up_scale); + pdi.transform.basis.set_axis(2, v_z * scale); } + int cpos = 0; - - int cpos=0; - - while(cpos<col_count) { + while (cpos < col_count) { if (cphase[cpos].pos > time) break; @@ -385,28 +362,23 @@ void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const Pa cpos--; - - if (cpos==-1) - pdi.color=Color(1,1,1,1); + if (cpos == -1) + pdi.color = Color(1, 1, 1, 1); else { - if (cpos==col_count-1) - pdi.color=cphase[cpos].color; + if (cpos == col_count - 1) + pdi.color = cphase[cpos].color; else { - float diff = (cphase[cpos+1].pos-cphase[cpos].pos); - if (diff>0) - pdi.color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (time - cphase[cpos].pos) / diff ); + float diff = (cphase[cpos + 1].pos - cphase[cpos].pos); + if (diff > 0) + pdi.color = cphase[cpos].color.linear_interpolate(cphase[cpos + 1].color, (time - cphase[cpos].pos) / diff); else - pdi.color=cphase[cpos+1].color; + pdi.color = cphase[cpos + 1].color; } } - - draw_info_order[i]=&pdi; - + draw_info_order[i] = &pdi; } - - SortArray<ParticleDrawInfo*,_ParticleSorterSW> particle_sort; - particle_sort.sort(&draw_info_order[0],p_system->amount); - + SortArray<ParticleDrawInfo *, _ParticleSorterSW> particle_sort; + particle_sort.sort(&draw_info_order[0], p_system->amount); } |
