pl_system_t* pl_new_root_system(pl_world_t *world, const char *name, double m, double gm, double obliquity, double siderealPeriod, double eqRadius, double flattening) { assert(world); pl_system_t *sys = smalloc(sizeof(pl_system_t)); obj_array_init(&sys->orbits); obj_array_init(&sys->astroObjs); obj_array_init(&sys->rigidObjs); sys->name = strdup(name); sys->world = world; sys->parent = NULL; lwcoord_t p; lwc_set(&p, 0.0, 0.0, 0.0); quaternion_t q = q_rot(1.0, 0.0, 0.0, DEG_TO_RAD(obliquity)); sys->orbitalBody = pl_new_obj(world, name, m, gm, &p, q, siderealPeriod, obliquity, eqRadius, flattening); sys->orbitalBody->kepler = NULL; world->rootSys = sys; pl_sys_set_current_pos(sys); return sys; }
static float sol_test_body(float dt, float T[3], float V[3], const struct v_ball *up, const struct s_vary *vary, const struct v_body *bp) { float U[3], O[3], E[4], W[3], u; const struct b_node *np = vary->base->nv + bp->base->ni; sol_body_p(O, vary, bp, 0.0f); sol_body_v(W, vary, bp, dt); sol_body_e(E, vary, bp, 0.0f); /* * For rotating bodies, rather than rotate every normal and vertex * of the body, we temporarily pretend the ball is rotating and * moving about a static body. */ /* * Linear velocity of a point rotating about the origin: * v = w x p */ if (E[0] != 1.0f || sol_body_w(vary, bp)) { /* The body has a non-identity orientation or it is rotating. */ struct v_ball ball; float e[4], p0[3], p1[3]; const float z[3] = { 0 }; /* First, calculate position at start and end of time interval. */ v_sub(p0, up->p, O); v_cpy(p1, p0); q_conj(e, E); q_rot(p0, e, p0); v_mad(p1, p1, up->v, dt); v_mad(p1, p1, W, -dt); sol_body_e(e, vary, bp, dt); q_conj(e, e); q_rot(p1, e, p1); /* Set up ball struct with values relative to body. */ ball = *up; v_cpy(ball.p, p0); /* Calculate velocity from start/end positions and time. */ v_sub(ball.v, p1, p0); v_scl(ball.v, ball.v, 1.0f / dt); if ((u = sol_test_node(dt, U, &ball, vary->base, np, z, z)) < dt) { /* Compute the final orientation. */ sol_body_e(e, vary, bp, u); /* Return world space coordinates. */ q_rot(T, e, U); v_add(T, O, T); /* Move forward. */ v_mad(T, T, W, u); /* Express "non-ball" velocity. */ q_rot(V, e, ball.v); v_sub(V, up->v, V); dt = u; } } else { if ((u = sol_test_node(dt, U, up, vary->base, np, O, W)) < dt) { v_cpy(T, U); v_cpy(V, W); dt = u; } } return dt; }