void plMassSet(PLmass *mo, float m, float cox, float coy, float coz, float ixx, float iyy, float izz, float ixy, float ixz, float iyz) { memset(mo, 0, sizeof(PLmass)); mo->m = m; mo->I[0][0] = ixx; mo->I[1][1] = iyy; mo->I[2][2] = izz; mo->I[0][1] = ixy; mo->I[1][0] = ixy; mo->I[0][2] = ixz; mo->I[2][0] = ixz; mo->I[1][2] = iyz; mo->I[2][1] = iyz; mo->cog = vf3_set(cox, coy, coz); mf3_inv2(mo->I_inv, mo->I); mo->minMass = 0.0f; }
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; } } }
void plAttachParticleSystem3f(PLparticles *ps, PLobject *obj, float x, float y, float z) { assert(ps != NULL); assert(obj != NULL); assert(ps->obj == NULL); obj_array_push(&obj->psystem, ps); ps->obj = obj; if (obj->parent) { obj_array_push(&obj->parent->sys->world->partSys, ps); } else { obj_array_push(&obj->sys->world->partSys, ps); } ps->p = vf3_set(x, y, z); }
/*! \param a Semi-major axis \param b Semi-minor axis \param ecc Eccentricity of orbit \param GM Gravitational parameter of orbited object GM \param t Absolute time in seconds. */ float3 plOrbitPosAtTime(pl_keplerelems_t *orbit, double GM, double t) { long double meanMotion = plMeanMotion(GM, orbit->a); long double eccAnomaly = pl_ecc_anomaly(orbit->ecc, meanMotion, t); /* Compute x, y from anomaly, y is pointing in the direction of the periapsis */ double y = orbit->a * cos(eccAnomaly) - orbit->a * orbit->ecc; // NOTE: on the plane we usually do x = a cos t double x = -orbit->b * sin(eccAnomaly); // Since we use y as primary axis, x points downwards quaternion_t q = orbit->qOrbit; float3 v = vf3_set(x, y, 0.0); v = v_q_rot(v, q); assert(isfinite(v.x)); assert(isfinite(v.y)); assert(isfinite(v.z)); return v; }
void plMassTranslate(PLmass *m, float dx, float dy, float dz) { float3x3 re; mf3_ident(re); float3 r = vf3_set(dx, dy, dz); float rdot = vf3_dot(r, r); re[0][0] = rdot; re[1][1] = rdot; re[2][2] = rdot; float3x3 rout; vf3_outprod(rout, r, r); float3x3 madj; mf3_sub(madj, re, rout); float3x3 mtmp; mf3_s_mul(mtmp, madj, m->m); mf3_add2(m->I, mtmp); m->cog = vf3_add(m->cog, r); mf3_inv2(m->I_inv, m->I); }
float3 ooGeoEllipseSegPoint(OOellipse *e, double t) { double pos = fmod(t, (double)(e->vec.length)); size_t i = (size_t) pos; float3 a = (float3) e->vec.elems[(i + 1) % e->vec.length]; float3 b = (float3) e->vec.elems[i % e->vec.length]; double frac = pos - floor(pos); float3 av, bv; av = a; bv = b; // Lineraly interpolate between point b and a float3 abdiff = vf3_sub(av, bv); float3 tmp = vf3_set(frac, frac, frac); float3 fv = vf3_mul(abdiff, tmp);//v_s_mul(abdiff, (float)frac); BUG IN v_s_mul??? float3 res = vf3_add(bv, fv); return res; }
void pl_sys_step(pl_system_t *sys, double dt) { // Add gravitational forces for (size_t i = 0; i < sys->rigidObjs.length ; i ++) { pl_object_t *obj = sys->rigidObjs.elems[i]; double3 g = pl_bhut_compute_gravity(sys->world->bhut_tree, obj); pl_object_force3fv(obj, vf3_set(g.x, g.y, g.z)); PL_CHECK_OBJ(obj); float3 f12 = pl_compute_gravity(sys->orbitalBody, obj); pl_object_set_gravity3fv(obj, f12); pl_object_force3fv(obj, f12); PL_CHECK_OBJ(obj); if (sys->parent) { f12 = pl_compute_gravity(sys->parent->orbitalBody, obj); pl_object_set_gravity3fv(obj, f12); pl_object_force3fv(obj, f12); PL_CHECK_OBJ(obj); } float3 drag = pl_object_compute_drag(obj); pl_object_force3fv(obj, drag); PL_CHECK_OBJ(obj); pl_object_step(obj, dt); } pl_sys_update_current_pos(sys, dt); for (size_t i = 0; i < sys->orbits.length ; i ++) { pl_sys_step(sys->orbits.elems[i], dt); } }
void plSetEmitterDirection3f(PLparticles *ps, float x, float y, float z) { ps->v = vf3_set(x, y, z); }
void pl_object_clear_(pl_object_t *obj) { obj->f_ack = vf3_set(0.0f, 0.0f, 0.0f); obj->t_ack = vf3_set(0.0f, 0.0f, 0.0f); }