public static void sol_body_v(float[] v, s_file fp, s_body bp) { if (bp.m_pi >= 0 && fp.m_pv[bp.m_pi].m_f != 0) { s_path pp = fp.m_pv[bp.m_pi]; s_path pq = fp.m_pv[pp.m_pi]; Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_scl(v, v, 1.0f / pp.m_t); if (pp.m_s != 0) { Vec3.v_scl(v, v, derp(bp.m_t / pp.m_t)); } } else { v[0] = 0.0f; v[1] = 0.0f; v[2] = 0.0f; } }
public static float sol_test_body(float dt, float[] T, float[] V, s_ball up, s_file fp, s_body bp) { float u, t = dt; float[] U = new float[3]; float[] O = new float[3]; float[] W = new float[3]; s_node np = fp.m_nv[bp.m_ni]; sol_body_p(O, fp, bp); sol_body_v(W, fp, bp); if ((u = sol_test_node(t, U, up, fp, np, O, W)) < t) { Vec3.v_cpy(T, U); Vec3.v_cpy(V, W); t = u; } return(t); }
public static void sol_body_p(float[] p, s_file fp, s_body bp) { float[] v = new float[3]; if (bp.m_pi >= 0) { s_path pp = fp.m_pv[bp.m_pi]; s_path pq = fp.m_pv[pp.m_pi]; if (pp.m_s != 0) { Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_mad(p, pp.m_p, v, erp(bp.m_t / pp.m_t)); } else { Vec3.v_sub(v, pq.m_p, pp.m_p); Vec3.v_mad(p, pp.m_p, v, bp.m_t / pp.m_t); } } else { p[0] = 0.0f; p[1] = 0.0f; p[2] = 0.0f; } }
public static float sol_test_file(float dt, float[] T, float[] V, s_ball up, s_file fp) { float u, t = dt; float[] U = new float[3]; float[] W = new float[3]; int i; for (i = 0; i < fp.m_bc; i++) { s_body bp = fp.m_bv[i]; if ((u = sol_test_body(t, U, W, up, fp, bp)) < t) { Vec3.v_cpy(T, U); Vec3.v_cpy(V, W); t = u; } } return(t); }
public int sol_enum_mtrl(s_body bp, int mi) { int li, gi, c = 0; /* Count all lump geoms with this material. */ for (li = 0; li < bp.m_lc; li++) { int g0 = m_lv[bp.m_l0 + li].m_g0; int gc = m_lv[bp.m_l0 + li].m_gc; for (gi = 0; gi < gc; gi++) { if (m_gv[m_iv[g0 + gi]].m_mi == mi) { c++; } } } /* Count all body geoms with this material. */ for (gi = 0; gi < bp.m_gc; gi++) { if (m_gv[m_iv[bp.m_g0 + gi]].m_mi == mi) { c++; } } return(c); }
public static void sol_load_body(IntPtr fin, s_body bp) { Binary.get_index(fin, ref bp.m_pi); Binary.get_index(fin, ref bp.m_ni); Binary.get_index(fin, ref bp.m_l0); Binary.get_index(fin, ref bp.m_lc); Binary.get_index(fin, ref bp.m_g0); Binary.get_index(fin, ref bp.m_gc); }
public int sol_enum_body(s_body bp, int fl) { int c = 0; /* Count all geoms with this flag. */ for (int mi = 0; mi < m_mc; mi++) { if ((m_mv[mi].m_fl & fl) != 0) { c = c + sol_enum_mtrl(bp, mi); } } return(c); }
/* * Compute the positions of all bodies after DT seconds have passed. */ public static void sol_body_step(s_file fp, float dt) { int i; for (i = 0; i < fp.m_bc; i++) { s_body bp = fp.m_bv[i];// + i; if (bp.m_pi >= 0) { s_path pp = fp.m_pv[bp.m_pi]; if (pp.m_f != 0) { //volatile float t = bp.m_t; bp.m_t = (t += dt); if (t >= pp.m_t) { bp.m_t = 0; bp.m_pi = pp.m_pi; cmd.type = cmd_type.CMD_BODY_TIME; cmd.bodytime.bi = i; cmd.bodytime.t = bp.m_t; sol_cmd_enq(cmd); cmd.type = cmd_type.CMD_BODY_PATH; cmd.bodypath.bi = i; cmd.bodypath.pi = bp.m_pi; sol_cmd_enq(cmd); } } } } }
public s_mtrl sol_draw_body(s_body bp, s_mtrl mp, int fl, int decal) { int mi, li, gi; /* Iterate all materials of the correct opacity. */ for (mi = 0; mi < m_mc; mi++) { if ((m_mv[mi].m_fl & fl) != 0 && (m_mv[mi].m_fl & Solid.M_DECAL) == decal) { if (sol_enum_mtrl(bp, mi) != 0) { // Set the material state. mp = m_mv[mi].sol_draw_mtrl(mp); /* Render all geometry of that material. */ Video.Begin(Video.TRIANGLES); { for (li = 0; li < bp.m_lc; li++) { sol_draw_lump(m_lv[bp.m_l0 + li], mi); } for (gi = 0; gi < bp.m_gc; gi++) { sol_draw_geom(m_gv[m_iv[bp.m_g0 + gi]], mi); } } Video.End(); } } } return(mp); }
public static void game_run_cmd(Command cmd) { /* * Neverball <= 1.5.1 does not send explicit tilt axes, rotation * happens directly around view vectors. So for compatibility if * at the time of receiving tilt angles we have not yet received * the tilt axes, we use the view vectors. */ float[] f = new float[3]; if (client_state != 0) { s_ball[] up; float dt; int i; switch (cmd.type) { case cmd_type.CMD_END_OF_UPDATE: game_run_cmd_got_tilt_axes = 0; if (first_update != 0) { first_update = 0; break; } /* Compute gravity for particle effects. */ if (status == (int)GAME.GAME_GOAL) { game_common.game_tilt_grav(f, game_run_cmd_gup, tilt); } else { game_common.game_tilt_grav(f, game_run_cmd_gdn, tilt); } /* Step particle, goal and jump effects. */ if (ups > 0) { dt = 1.0f / (float)ups; if (goal_e != 0 && goal_k < 1.0f) { goal_k += dt; } if (jump_b != 0) { jump_dt += dt; if (1.0f < jump_dt) { jump_b = 0; } } Part.part_step(f, dt); } break; case cmd_type.CMD_MAKE_BALL: /* Allocate a new ball and mark it as the current ball. */ up = new s_ball[file.m_uc + 1]; { for (i = 0; i < file.m_uc; i++) { up[i] = file.m_uv[i]; } up[file.m_uc] = new s_ball(); } { file.m_uv = up; curr_ball = file.m_uc; file.m_uc++; } break; case cmd_type.CMD_MAKE_ITEM: /* Allocate and initialise a new item. */ { s_item[] hp = new s_item[file.m_hc + 1]; { for (i = 0; i < file.m_hc; i++) { hp[i] = file.m_hv[i]; } } { s_item h = new s_item(); Vec3.v_cpy(h.m_p, cmd.mkitem.p); h.m_t = cmd.mkitem.t; h.m_n = cmd.mkitem.n; file.m_hv = hp; file.m_hv[file.m_hc] = h; file.m_hc++; } } break; case cmd_type.CMD_PICK_ITEM: /* Set up particle effects and discard the item. */ { s_item hp = file.m_hv[cmd.pkitem.hi]; Item.item_color(hp, f); Part.part_burst(hp.m_p, f); hp.m_t = Solid.ITEM_NONE; } break; case cmd_type.CMD_TILT_ANGLES: if (game_run_cmd_got_tilt_axes == 0) { game_common.game_tilt_axes(tilt, view_e); } tilt.rx = cmd.tiltangles.x; tilt.rz = cmd.tiltangles.z; break; case cmd_type.CMD_SOUND: /* Play the sound, then free its file name. */ if (cmd.sound.n != null) { Audio.audio_play(cmd.sound.n, cmd.sound.a); /* * FIXME Command memory management should be done * elsewhere and done properly. */ cmd.sound.n = null; } break; case cmd_type.CMD_TIMER: timer = cmd.timer.t; break; case cmd_type.CMD_STATUS: status = cmd.status.t; break; case cmd_type.CMD_COINS: coins = cmd.coins.n; break; case cmd_type.CMD_JUMP_ENTER: jump_b = 1; jump_e = 0; jump_dt = 0.0f; break; case cmd_type.CMD_JUMP_EXIT: jump_e = 1; break; case cmd_type.CMD_BODY_PATH: file.m_bv[cmd.bodypath.bi].m_pi = cmd.bodypath.pi; break; case cmd_type.CMD_BODY_TIME: file.m_bv[cmd.bodytime.bi].m_t = cmd.bodytime.t; break; case cmd_type.CMD_GOAL_OPEN: /* * Enable the goal and make sure it's fully visible if * this is the first update. */ if (goal_e == 0) { goal_e = 1; goal_k = first_update != 0 ? 1.0f : 0.0f; } break; case cmd_type.CMD_SWCH_ENTER: file.m_xv[cmd.swchenter.xi].m_e = 1; break; case cmd_type.CMD_SWCH_TOGGLE: file.m_xv[cmd.swchtoggle.xi].m_f = file.m_xv[cmd.swchtoggle.xi].m_f == 0 ? 1 : 0; break; case cmd_type.CMD_SWCH_EXIT: file.m_xv[cmd.swchexit.xi].m_e = 0; break; case cmd_type.CMD_UPDATES_PER_SECOND: ups = cmd.ups.n; break; case cmd_type.CMD_BALL_RADIUS: file.m_uv[curr_ball].m_r = cmd.ballradius.r; break; case cmd_type.CMD_CLEAR_ITEMS: if (file.m_hv != null) { file.m_hv = null; } file.m_hc = 0; break; case cmd_type.CMD_CLEAR_BALLS: if (file.m_uv != null) { file.m_uv = null; } file.m_uc = 0; break; case cmd_type.CMD_BALL_POSITION: Vec3.v_cpy(file.m_uv[curr_ball].m_p, cmd.ballpos.p); break; case cmd_type.CMD_BALL_BASIS: Vec3.v_cpy(file.m_uv[curr_ball].m_e[0], cmd.ballbasis.e[0]); Vec3.v_cpy(file.m_uv[curr_ball].m_e[1], cmd.ballbasis.e[1]); Vec3.v_crs(file.m_uv[curr_ball].m_e[2], file.m_uv[curr_ball].m_e[0], file.m_uv[curr_ball].m_e[1]); break; case cmd_type.CMD_VIEW_POSITION: Vec3.v_cpy(view_p, cmd.viewpos.p); break; case cmd_type.CMD_VIEW_CENTER: Vec3.v_cpy(view_c, cmd.viewcenter.c); break; case cmd_type.CMD_VIEW_BASIS: Vec3.v_cpy(view_e[0], cmd.viewbasis.e[0]); Vec3.v_cpy(view_e[1], cmd.viewbasis.e[1]); Vec3.v_crs(view_e[2], view_e[0], view_e[1]); break; case cmd_type.CMD_CURRENT_BALL: curr_ball = cmd.currball.ui; break; case cmd_type.CMD_PATH_FLAG: file.m_pv[cmd.pathflag.pi].m_f = cmd.pathflag.f; break; case cmd_type.CMD_STEP_SIMULATION: /* * Simulate body motion. * * This is done on the client side due to replay file size * concerns and isn't done as part of cmd_type.CMD_END_OF_UPDATE to * match the server state as closely as possible. Body * time is still synchronised with the server on a * semi-regular basis and path indices are handled through * cmd_type.CMD_BODY_PATH, thus this code doesn't need to be as * sophisticated as sol_body_step. */ dt = cmd.stepsim.dt; for (i = 0; i < file.m_bc; i++) { s_body bp = file.m_bv[i]; // + i; if (bp.m_pi >= 0) { s_path pp = file.m_pv[bp.m_pi]; if (pp.m_f != 0) { bp.m_t += dt; } } } break; case cmd_type.CMD_MAP: /* * Note if the loaded map matches the server's * expectations. (No, this doesn't actually load a map, * yet. Something else somewhere else does.) */ cmd.map.name = null; game_compat_map = version_x == cmd.map.version.x ? 1 : 0; break; case cmd_type.CMD_TILT_AXES: game_run_cmd_got_tilt_axes = 1; Vec3.v_cpy(tilt.x, cmd.tiltaxes.x); Vec3.v_cpy(tilt.z, cmd.tiltaxes.z); break; case cmd_type.CMD_NONE: case cmd_type.CMD_MAX: break; } } }
void sol_load_objects(int s) { int i; /* Here we sort geometry into display lists by material type. */ for (i = 0; i < m_bc; i++) { s_body bp = m_bv[i];// + i; int on = sol_enum_body(bp, Solid.M_OPAQUE); int tn = sol_enum_body(bp, Solid.M_TRANSPARENT); int rn = sol_enum_body(bp, Solid.M_REFLECTIVE); int dn = sol_enum_body(bp, Solid.M_DECAL); /* Draw all opaque geometry, decals last. */ if (on != 0) { m_bv[i].draw_ol = true; m_bv[i].sol_draw_list_ol(this); } else { m_bv[i].draw_ol = false; } /* Draw all translucent geometry, decals first. */ if (tn != 0) { m_bv[i].draw_tl = true; m_bv[i].sol_draw_list_tl(this); } else { m_bv[i].draw_tl = false; } /* Draw all reflective geometry. */ if (rn != 0) { m_bv[i].draw_rl = true; m_bv[i].sol_draw_list_rl(this); } else { m_bv[i].draw_rl = false; } /* Draw all shadowed geometry. */ if (s != 0 && (on != 0 || rn != 0)) { m_bv[i].draw_sl = true; m_bv[i].sol_shad_list(this); } else { m_bv[i].draw_sl = false; } } }