void plStepParticleSystem(PLparticles *ps, float dt) { assert(ps != NULL); if (ps->enabled == false) return; size_t activeParticles = 0; for (size_t i = 0 ; i < ps->particleCount ; ++i) { if (ps->particles[i].active) { ps->particles[i].p += vf3_s_mul(ps->particles[i].v, dt) + vf3_s_mul(ps->obj->v, dt); ps->particles[i].age += dt; activeParticles++; if (ps->particles[i].age > ps->particles[i].lifeTime) { ps->particles[i].active = false; int_array_push(&ps->freeParticles, i); activeParticles --; } } } // Auto disable if (ps->autoDisable) { if (activeParticles == 0) { ps->enabled = false; } return; } // Not off or disabled, emitt new particles float newPartCount = ps->emissionRate * dt * (1.0 + rand_percent(10)); float intPart; float frac = modff(newPartCount, &intPart); unsigned newParticles = (unsigned) intPart; // The fraction is handled with randomisation int rval = random() % 128; if ((float)rval/128.0f < frac) newParticles ++; for (unsigned i = 0 ; i < newParticles ; ++i) { if (ps->freeParticles.length > 0) { int i = int_array_remove(&ps->freeParticles, 0); ps->particles[i].active = true; ps->particles[i].age = 0.0; // Adjust lifetime by +-20 % ps->particles[i].lifeTime = ps->lifeTime + ps->lifeTime * rand_percent(20); ps->particles[i].p = v_q_rot(ps->p, ps->obj->q); ps->particles[i].v = v_q_rot(ps->v * vf3_set(rand_percent(10), rand_percent(10), rand_percent(10)), ps->obj->q); ps->particles[i].rgb = ps->rgb; } else { break; } } }
float3 pl_compute_gravity(pl_astrobody_t *a, pl_object_t *b) { float3 dist = lwc_dist(&b->p, &a->obj.p); double r12 = vf3_abs_square(dist); float3 ndist = vf3_normalise(dist); float3 f12 = vf3_s_mul(ndist, //-PL_G * (a->obj.m.m * b->m.m / r12)); -a->GM * b->m.m / r12); assert(isfinite(dist.x)); assert(isfinite(dist.y)); assert(isfinite(dist.z)); assert(isfinite(ndist.x)); assert(isfinite(ndist.y)); assert(isfinite(ndist.z)); assert(isfinite(r12)); assert(isfinite(f12.x)); assert(isfinite(f12.y)); assert(isfinite(f12.z)); return f12; }
void pl_sys_update_current_pos(pl_system_t *sys, double dt) { if (sys->parent) { double t = sim_time_get_jd(); if (sys->orbitalBody->tUpdate > 0) { lwc_translate3fv(&sys->orbitalBody->obj.p, vf3_s_mul(sys->orbitalBody->obj.v, dt)); sys->orbitalBody->tUpdate --; } else { float3 newPos = plOrbitPosAtTime(sys->orbitalBody->kepler, sys->parent->orbitalBody->GM, t*PL_SEC_PER_DAY); float3 nextPos = plOrbitPosAtTime(sys->orbitalBody->kepler, sys->parent->orbitalBody->GM, t*PL_SEC_PER_DAY + (double)sys->orbitalBody->orbitFixationPeriod * dt); float3 vel = vf3_s_div(vf3_sub(nextPos, newPos), (double)sys->orbitalBody->orbitFixationPeriod * dt); sys->orbitalBody->obj.p = sys->parent->orbitalBody->obj.p; lwc_translate3fv(&sys->orbitalBody->obj.p, newPos); sys->orbitalBody->obj.v = sys->parent->orbitalBody->obj.v + vel; // Reset tUpdate; sys->orbitalBody->tUpdate = sys->orbitalBody->orbitFixationPeriod; } sys->orbitalBody->obj.q = plSideralRotationAtTime(sys->orbitalBody, t); } else { lwc_set(&sys->orbitalBody->obj.p, 0.0, 0.0, 0.0); } }
void plMassRotateQ(PLmass *m, quaternion_t q) { float3x3 mat; q_mf3_convert(mat, q); plMassRotateM(m, mat); } void plMassAdd(PLmass * restrict md, const PLmass * restrict ms) { float recip = 1.0f / (md->m + ms->m); float3 a = vf3_s_mul(md->cog, md->m); float3 b = vf3_s_mul(ms->cog, ms->m); float3 c = vf3_add(a, b); md->cog = vf3_s_mul(c, recip); md->m += ms->m; for (int i = 0 ; i < 3 ; ++ i) { md->I[i] = vf3_add(md->I[i], ms->I[i]); } mf3_inv2(md->I_inv, md->I); } void plMassMod(PLmass *m, float newMass) {