Beispiel #1
0
        public static int sol_test_back(float dt,
                                        s_ball up,
                                        s_side sp,
                                        float[] o,
                                        float[] w)
        {
            float[] q = new float[3];

            /* If the ball is not in front of the plane, the test passes. */

            Vec3.v_sub(q, up.m_p, o);

            if (Vec3.v_dot(q, sp.m_n) - sp.m_d - up.m_r <= 0)
            {
                return(1);
            }

            /* If it's not in front of the plane after DT seconds, the test passes. */

            Vec3.v_mad(q, q, up.m_v, dt);

            if (Vec3.v_dot(q, sp.m_n) - sp.m_d - up.m_r <= 0)
            {
                return(1);
            }

            /* Else, test fails. */

            return(0);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        public static float sol_test_side(float dt,
                                          float[] T,
                                          s_ball up,
                                          s_file fp,
                                          s_lump lp,
                                          s_side sp,
                                          float[] o,
                                          float[] w)
        {
            float t = v_side(T, o, w, sp.m_n, sp.m_d, up.m_p, up.m_v, up.m_r);
            int   i;

            if (t < dt)
            {
                for (i = 0; i < lp.m_sc; i++)
                {
                    s_side sq = fp.m_sv[fp.m_iv[lp.m_s0 + i]];

                    if (sp != sq &&
                        Vec3.v_dot(T, sq.m_n) -
                        Vec3.v_dot(o, sq.m_n) -
                        Vec3.v_dot(w, sq.m_n) * t > sq.m_d)
                    {
                        return((float)LARGE);
                    }
                }
            }
            return(t);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
 public static float sol_test_vert(float dt,
                                   float[] T,
                                   s_ball up,
                                   s_vert vp,
                                   float[] o,
                                   float[] w)
 {
     return(v_vert(T, o, vp.m_p, w, up.m_p, up.m_v, up.m_r));
 }
Beispiel #6
0
        public static float sol_test_node(float dt,
                                          float[] T,
                                          s_ball up,
                                          s_file fp,
                                          s_node np,
                                          float[] o,
                                          float[] w)
        {
            float u, t = dt;

            float[] U = new float[3];
            int     i;

            /* Test all lumps */

            for (i = 0; i < np.m_lc; i++)
            {
                s_lump lp = fp.m_lv[np.m_l0 + i];

                if ((u = sol_test_lump(t, U, up, fp, lp, o, w)) < t)
                {
                    Vec3.v_cpy(T, U);
                    t = u;
                }
            }

            /* Test in front of this node */

            if (np.m_ni >= 0 &&
                sol_test_fore(t, up, fp.m_sv[np.m_si], o, w) != 0)
            {
                s_node nq = fp.m_nv[np.m_ni];

                if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
                {
                    Vec3.v_cpy(T, U);
                    t = u;
                }
            }

            /* Test behind this node */

            if (np.m_nj >= 0 &&
                sol_test_back(t, up, fp.m_sv[np.m_si], o, w) != 0)
            {
                s_node nq = fp.m_nv[np.m_nj];

                if ((u = sol_test_node(t, U, up, fp, nq, o, w)) < t)
                {
                    Vec3.v_cpy(T, U);
                    t = u;
                }
            }

            return(t);
        }
Beispiel #7
0
        /*
         * Compute the positions of all balls after DT seconds have passed.
         */
        public static void sol_ball_step(s_file fp, float dt)
        {
            int i;

            for (i = 0; i < fp.m_uc; i++)
            {
                s_ball up = fp.m_uv[i];// + i;

                Vec3.v_mad(up.m_p, up.m_p, up.m_v, dt);

                sol_rotate(up.m_e, up.m_w, dt);
            }
        }
Beispiel #8
0
        public static float sol_test_edge(float dt,
                                          float[] T,
                                          s_ball up,
                                          s_file fp,
                                          s_edge ep,
                                          float[] o,
                                          float[] w)
        {
            float[] q = new float[3];
            float[] u = new float[3];

            Vec3.v_cpy(q, fp.m_vv[ep.m_vi].m_p);
            Vec3.v_sub(u, fp.m_vv[ep.m_vj].m_p,
                       fp.m_vv[ep.m_vi].m_p);

            return(v_edge(T, o, q, u, w, up.m_p, up.m_v, up.m_r));
        }
Beispiel #9
0
        public static void sol_load_ball(IntPtr fin, s_ball bp)
        {
            Binary.get_array(fin, bp.m_p, 3);
            Binary.get_float(fin, ref bp.m_r);

            bp.m_e[0][0] = 1.0f;
            bp.m_e[0][1] = 0.0f;
            bp.m_e[0][2] = 0.0f;

            bp.m_e[1][0] = 0.0f;
            bp.m_e[1][1] = 1.0f;
            bp.m_e[1][2] = 0.0f;

            bp.m_e[2][0] = 0.0f;
            bp.m_e[2][1] = 0.0f;
            bp.m_e[2][2] = 1.0f;
        }
Beispiel #10
0
        /*
         * Compute the lnew  linear and angular velocities of  a bouncing ball.
         * Q  gives the  position  of the  point  of impact  and  W gives  the
         * velocity of the object being impacted.
         */
        public static float sol_bounce(s_ball up,
                                       float[] q,
                                       float[] w,
                                       float dt)
        {
            float[] n = new float[3];
            float[] r = new float[3];
            float[] d = new float[3];
            float   vn, wn;

            float[] p = up.m_p;
            float[] v = up.m_v;

            /* Find the normal of the impact. */

            Vec3.v_sub(r, p, q);
            Vec3.v_sub(d, v, w);
            Vec3.v_nrm(n, r);

            /* Find the lnew angular velocity. */

            Vec3.v_crs(up.m_w, d, r);
            Vec3.v_scl(up.m_w, up.m_w, -1.0f / (up.m_r * up.m_r));

            /* Find the lnew linear velocity. */

            vn = Vec3.v_dot(v, n);
            wn = Vec3.v_dot(w, n);

            Vec3.v_mad(v, v, n, 1.7f * (wn - vn));

            Vec3.v_mad(p, q, n, up.m_r);

            /* Return the "energy" of the impact, to determine the sound amplitude. */

            return(System.Math.Abs(Vec3.v_dot(n, d)));
        }
Beispiel #11
0
        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;
                }
            }
        }
Beispiel #12
0
        public static float sol_test_lump(float dt,
                                          float[] T,
                                          s_ball up,
                                          s_file fp,
                                          s_lump lp,
                                          float[] o,
                                          float[] w)
        {
            float[] U = new float[3] {
                0.0f, 0.0f, 0.0f
            };

            float u, t = dt;
            int   i;

            /* Short circuit a non-solid lump. */

            if ((lp.m_fl & Solid.L_DETAIL) != 0)
            {
                return(t);
            }

            /* Test all verts */

            if (up.m_r > 0.0f)
            {
                for (i = 0; i < lp.m_vc; i++)
                {
                    s_vert vp = fp.m_vv[fp.m_iv[lp.m_v0 + i]];

                    if ((u = sol_test_vert(t, U, up, vp, o, w)) < t)
                    {
                        Vec3.v_cpy(T, U);
                        t = u;
                    }
                }
            }

            /* Test all edges */

            if (up.m_r > 0.0f)
            {
                for (i = 0; i < lp.m_ec; i++)
                {
                    s_edge ep = fp.m_ev[fp.m_iv[lp.m_e0 + i]];

                    if ((u = sol_test_edge(t, U, up, fp, ep, o, w)) < t)
                    {
                        Vec3.v_cpy(T, U);
                        t = u;
                    }
                }
            }

            /* Test all sides */

            for (i = 0; i < lp.m_sc; i++)
            {
                s_side sp = fp.m_sv[fp.m_iv[lp.m_s0 + i]];

                if ((u = sol_test_side(t, U, up, fp, lp, sp, o, w)) < t)
                {
                    Vec3.v_cpy(T, U);
                    t = u;
                }
            }
            return(t);
        }
Beispiel #13
0
        /*
         * Step the physics forward DT  seconds under the influence of gravity
         * vector G.  If the ball gets pinched between two moving solids, this
         * loop might not terminate.  It  is better to do something physically
         * impossible than  to lock up the game.   So, if we make  more than C
         * iterations, punt it.
         */

        public static float sol_step(s_file fp, float[] g, float dt, int ui, ref int m, bool m_IsNull)
        {
            float d, e, nt, b = 0.0f, tt = dt;

            float[] P = new float[3];
            float[] V = new float[3];
            float[] v = new float[3];
            float[] r = new float[3];
            float[] a = new float[3];
            int     c = 16;

            defer_cmds = 1;

            if (ui < fp.m_uc)
            {
                s_ball up = fp.m_uv[ui];

                /* If the ball is in contact with a surface, apply friction. */

                Vec3.v_cpy(a, up.m_v);
                Vec3.v_cpy(v, up.m_v);
                Vec3.v_cpy(up.m_v, g);

                if (!m_IsNull && sol_test_file(tt, P, V, up, fp) < 0.0005f)
                {
                    Vec3.v_cpy(up.m_v, v);
                    Vec3.v_sub(r, P, up.m_p);

                    if ((d = Vec3.v_dot(r, g) / (Vec3.v_len(r) * Vec3.v_len(g))) > 0.999f)
                    {
                        if ((e = (Vec3.v_len(up.m_v) - dt)) > 0.0f)
                        {
                            /* Scale the linear velocity. */

                            Vec3.v_nrm(up.m_v, up.m_v);
                            Vec3.v_scl(up.m_v, up.m_v, e);

                            /* Scale the angular velocity. */

                            Vec3.v_sub(v, V, up.m_v);
                            Vec3.v_crs(up.m_w, v, r);
                            Vec3.v_scl(up.m_w, up.m_w, -1.0f / (up.m_r * up.m_r));
                        }
                        else
                        {
                            /* Friction has brought the ball to a stop. */

                            up.m_v[0] = 0.0f;
                            up.m_v[1] = 0.0f;
                            up.m_v[2] = 0.0f;

                            m++;
                        }
                    }
                    else
                    {
                        Vec3.v_mad(up.m_v, v, g, tt);
                    }
                }
                else
                {
                    Vec3.v_mad(up.m_v, v, g, tt);
                }

                /* Test for collision. */

                while (c > 0 && tt > 0 && tt > (nt = sol_test_file(tt, P, V, up, fp)))
                {
                    cmd.type       = cmd_type.CMD_STEP_SIMULATION;
                    cmd.stepsim.dt = nt;
                    sol_cmd_enq(cmd);

                    sol_body_step(fp, nt);
                    sol_swch_step(fp, nt);
                    sol_ball_step(fp, nt);

                    tt -= nt;

                    if (b < (d = sol_bounce(up, P, V, nt)))
                    {
                        b = d;
                    }

                    c--;
                }

                cmd.type       = cmd_type.CMD_STEP_SIMULATION;
                cmd.stepsim.dt = tt;
                sol_cmd_enq(cmd);

                sol_body_step(fp, tt);
                sol_swch_step(fp, tt);
                sol_ball_step(fp, tt);
            }

            sol_cmd_enq_deferred();
            defer_cmds = 0;

            return(b);
        }