Ejemplo n.º 1
0
Archivo: game.c Proyecto: rlk/neverball
void game_get_pos(float p[3], float e[3][3])
{
    v_cpy(p,    file.vary.uv[ball].p);
    v_cpy(e[0], file.vary.uv[ball].e[0]);
    v_cpy(e[1], file.vary.uv[ball].e[1]);
    v_cpy(e[2], file.vary.uv[ball].e[2]);
}
Ejemplo n.º 2
0
static void game_draw_vect_prim(const struct s_file *fp, GLenum mode)
{
    float p[3];
    float x[3];
    float z[3];
    float r;

    v_cpy(p, fp->uv[ball].p);
    v_cpy(x, view_e[0]);
    v_cpy(z, view_e[2]);

    r = fp->uv[ball].r;

    glBegin(mode);
    {
        glColor4f(1.0f, 1.0f, 0.5f, 0.5f);
        glVertex3f(p[0] - x[0] * r,
                   p[1] - x[1] * r,
                   p[2] - x[2] * r);

        glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
        glVertex3f(p[0] + z[0] * view_m,
                   p[1] + z[1] * view_m,
                   p[2] + z[2] * view_m);

        glColor4f(1.0f, 1.0f, 0.0f, 0.5f);
        glVertex3f(p[0] + x[0] * r,
                   p[1] + x[1] * r,
                   p[2] + x[2] * r);
    }
    glEnd();
}
Ejemplo n.º 3
0
Archivo: game.c Proyecto: rlk/neverball
void game_set_pos(float p[3], float e[3][3])
{
    v_cpy(file.vary.uv[ball].p,    p);
    v_cpy(file.vary.uv[ball].e[0], e[0]);
    v_cpy(file.vary.uv[ball].e[1], e[1]);
    v_cpy(file.vary.uv[ball].e[2], e[2]);
}
Ejemplo n.º 4
0
static float sol_test_lump(float dt,
                           float T[3],
                           const struct v_ball *up,
                           const struct s_base *base,
                           const struct b_lump *lp,
                           const float o[3],
                           const float w[3])
{
    float U[3] = { 0.0f, 0.0f, 0.0f };
    float u, t = dt;
    int i;

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

    if (lp->fl & L_DETAIL) return t;

    /* Test all verts */

    if (up->r > 0.0f)
        for (i = 0; i < lp->vc; i++)
        {
            const struct b_vert *vp = base->vv + base->iv[lp->v0 + i];

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

    /* Test all edges */

    if (up->r > 0.0f)
        for (i = 0; i < lp->ec; i++)
        {
            const struct b_edge *ep = base->ev + base->iv[lp->e0 + i];

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

    /* Test all sides */

    for (i = 0; i < lp->sc; i++)
    {
        const struct b_side *sp = base->sv + base->iv[lp->s0 + i];

        if ((u = sol_test_side(t, U, up, base, lp, sp, o, w)) < t)
        {
            v_cpy(T, U);
            t = u;
        }
    }
    return t;
}
Ejemplo n.º 5
0
static void game_cmd_tiltaxes(void)
{
    cmd.type = CMD_TILT_AXES;

    v_cpy(cmd.tiltaxes.x, tilt.x);
    v_cpy(cmd.tiltaxes.z, tilt.z);

    game_proxy_enq(&cmd);
}
Ejemplo n.º 6
0
static void 
pl_check_bounds(Polygon * pl, const vec p)
{
    if (pl->last > 1){
		check_bounds(&pl->bb, p);
    }
    else{
        v_cpy(pl->bb.min, p);
        v_cpy(pl->bb.max, p);
    }
}
Ejemplo n.º 7
0
/*
 * Compute appropriate tilt axes from the view basis.
 */
void game_tilt_axes(struct game_tilt *tilt, float view_e[3][3])
{
    const float Y[3] = { 0.0f, 1.0f, 0.0f };

    v_cpy(tilt->x, view_e[0]);
    v_cpy(tilt->z, view_e[2]);

    /* Handle possible top-down view. */

    if (fabsf(v_dot(view_e[1], Y)) < fabsf(v_dot(view_e[2], Y)))
        v_inv(tilt->z, view_e[1]);
}
Ejemplo n.º 8
0
static float sol_test_node(float dt,
                           float T[3],
                           const struct v_ball *up,
                           const struct s_base *base,
                           const struct b_node *np,
                           const float o[3],
                           const float w[3])
{
    float U[3], u, t = dt;
    int i;

    /* Test all lumps */

    for (i = 0; i < np->lc; i++)
    {
        const struct b_lump *lp = base->lv + np->l0 + i;

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

    /* Test in front of this node */

    if (np->ni >= 0 && sol_test_fore(t, up, base->sv + np->si, o, w))
    {
        const struct b_node *nq = base->nv + np->ni;

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

    /* Test behind this node */

    if (np->nj >= 0 && sol_test_back(t, up, base->sv + np->si, o, w))
    {
        const struct b_node *nq = base->nv + np->nj;

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

    return t;
}
Ejemplo n.º 9
0
static void 
pl_recalc_bounds(Polygon * pl)
{
    assert(pl);
    
    v_cpy(pl->bb.min, pl->points[0].co);
    v_cpy(pl->bb.max, pl->points[0].co);
    
    uint i;
    for (i=1; i < pl->last; i++){
        check_bounds(&pl->bb, pl->points[i].co);
	}
}
Ejemplo n.º 10
0
static void game_cmd_updview(void)
{
    cmd.type = CMD_VIEW_POSITION;
    v_cpy(cmd.viewpos.p, view.p);
    game_proxy_enq(&cmd);

    cmd.type = CMD_VIEW_CENTER;
    v_cpy(cmd.viewcenter.c, view.c);
    game_proxy_enq(&cmd);

    cmd.type = CMD_VIEW_BASIS;
    v_cpy(cmd.viewbasis.e[0], view.e[0]);
    v_cpy(cmd.viewbasis.e[1], view.e[1]);
    game_proxy_enq(&cmd);
}
Ejemplo n.º 11
0
static void game_cmd_updball(void)
{
    cmd.type = CMD_BALL_POSITION;
    v_cpy(cmd.ballpos.p, vary.uv[0].p);
    game_proxy_enq(&cmd);

    cmd.type = CMD_BALL_BASIS;
    v_cpy(cmd.ballbasis.e[0], vary.uv[0].e[0]);
    v_cpy(cmd.ballbasis.e[1], vary.uv[0].e[1]);
    game_proxy_enq(&cmd);

    cmd.type = CMD_BALL_PEND_BASIS;
    v_cpy(cmd.ballpendbasis.E[0], vary.uv[0].E[0]);
    v_cpy(cmd.ballpendbasis.E[1], vary.uv[0].E[1]);
    game_proxy_enq(&cmd);
}
Ejemplo n.º 12
0
int sol_load_lerp(struct s_lerp *fp, struct s_vary *vary)
{
    int i;

    fp->vary = vary;

    if (fp->vary->mc)
    {
        fp->mv = calloc(fp->vary->mc, sizeof (*fp->mv));
        fp->mc = fp->vary->mc;

        for (i = 0; i < fp->vary->mc; i++)
            fp->mv[i][CURR].pi = fp->vary->mv[i].pi;
    }

    if (fp->vary->uc)
    {
        fp->uv = calloc(fp->vary->uc, sizeof (*fp->uv));
        fp->uc = fp->vary->uc;

        for (i = 0; i < fp->vary->uc; i++)
        {
            e_cpy(fp->uv[i][CURR].e, fp->vary->uv[i].e);
            v_cpy(fp->uv[i][CURR].p, fp->vary->uv[i].p);
            e_cpy(fp->uv[i][CURR].E, fp->vary->uv[i].E);

            fp->uv[i][CURR].r = fp->vary->uv[i].r;
        }
    }

    sol_lerp_copy(fp);

    return 1;
}
Ejemplo n.º 13
0
static float sol_test_file(float dt,
                           float T[3], float V[3],
                           const struct v_ball *up,
                           const struct s_vary *vary)
{
    float U[3], W[3], u, t = dt;
    int i;

    for (i = 0; i < vary->bc; i++)
    {
        const struct v_body *bp = vary->bv + i;

        if ((u = sol_test_body(t, U, W, up, vary, bp)) < t)
        {
            v_cpy(T, U);
            v_cpy(V, W);
            t = u;
        }
    }
    return t;
}
Ejemplo n.º 14
0
PolyVert * pl_pop(Polygon * pl)
{
    assert(pl);
    
    if (pl->last){
        PolyVert * result= (PolyVert *)malloc(sizeof(PolyVert));
        pl->last--;
        PolyVert * last= pl->points + pl->last;
        v_cpy(result->co, last->co);
        result->flags= last->flags;
        
        return result;
    }
    
    return NULL;
}
Ejemplo n.º 15
0
static float sol_test_edge(float dt,
                           float T[3],
                           const struct v_ball *up,
                           const struct s_base *base,
                           const struct b_edge *ep,
                           const float o[3],
                           const float w[3])
{
    float q[3];
    float u[3];

    v_cpy(q, base->vv[ep->vi].p);
    v_sub(u, base->vv[ep->vj].p, base->vv[ep->vi].p);

    return v_edge(T, o, q, u, w, up->p, up->v, up->r);
}
Ejemplo n.º 16
0
PolyVert * 
pl_append(Polygon **pl_pt, const vec co, int flags)
{
    assert(co);

	Polygon * pl= pl_check_pointer(pl_pt);
    
    if (pl->last > pl->size) pl_expand(pl, pl->size);
	
    PolyVert * vx= pl->points + pl->last++;
    v_cpy(vx->co, co);
    vx->flags= flags;
    
    pl_check_bounds(pl, co);
    
    return vx;
}
Ejemplo n.º 17
0
void 
pl_extend_points(Polygon * pl, const vec * points, uint count)
{
    assert(pl);
    assert(points);
    
	PolyVert *tmp;
	
	pl_check_size(pl);
	
    uint i;
    for (i=0 ; i < count; i++){
		tmp= pl->points + pl->last++;
		tmp->flags= 0;
		v_cpy(tmp->co, points[i]);
	}
}
Ejemplo n.º 18
0
static void game_cmd_init_items(void)
{
    int i;

    cmd.type = CMD_CLEAR_ITEMS;
    game_proxy_enq(&cmd);

    for (i = 0; i < vary.hc; i++)
    {
        cmd.type = CMD_MAKE_ITEM;

        v_cpy(cmd.mkitem.p, vary.hv[i].p);

        cmd.mkitem.t = vary.hv[i].t;
        cmd.mkitem.n = vary.hv[i].n;

        game_proxy_enq(&cmd);
    }
}
Ejemplo n.º 19
0
PolyVert * 
pl_insert_point(Polygon * pl, uint pos, const vec p)
{
    assert(pl);
    assert(p);
    pl_check_size(pl);
    
    uint i= pl->last++;
    uint j= pl->last;
    for (; i >= pos; j=i--){
        pl->points[j]= pl->points[i];
	}
	
    PolyVert *vx= pl->points + i;
    v_cpy(vx->co, p);
    vx->flags= 0;
    
    pl_check_bounds(pl, p);
    
    return vx;
}
Ejemplo n.º 20
0
double Vector3D::horizontalAngle(const Vector3D & v) const 
{
  Vector3D v_cpy(*this);
  Vector3D v_cpy2(v);
  Vector3D v_signe;
  v_cpy.Z = 0; v_cpy2.Z = 0;

  if (v_cpy == 0 || v_cpy2 == 0)
    return 0;

  v_signe = v_cpy.crossProduct(v_cpy2);
  if (v_signe.Z > 0.0001) {
	  //std::cout << "angle : " << -acos((v_cpy.normalize()).scalarProduct(v_cpy2.normalize()))*(180/M_PI) << std::endl;
    return -acos((v_cpy.normalize()).scalarProduct(v_cpy2.normalize()))*(180/M_PI);
  } else if (v_signe.Z < -0.0001) {
	  //std::cout << "angle : " << acos((v_cpy.normalize()).scalarProduct(v_cpy2.normalize()))*(180/M_PI) << std::endl;

    return acos((v_cpy.normalize()).scalarProduct(v_cpy2.normalize()))*(180/M_PI);
  } else {
    return 0;
  }
}
Ejemplo n.º 21
0
float sol_step(struct s_vary *vary, const float *g, float dt, int ui, int *m)
{
    float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt, t;
    int c;

    union cmd cmd;

    if (ui < vary->uc)
    {
        struct v_ball *up = vary->uv + ui;

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

        v_cpy(a, up->v);
        v_cpy(v, up->v);
        v_cpy(up->v, g);

        if (m && sol_test_file(tt, P, V, up, vary) < 0.0005f)
        {
            v_cpy(up->v, v);
            v_sub(r, P, up->p);

            t = v_len(r) * v_len(g);
            if (t == 0.f)
            {
              t = SMALL;
            }
            
            if ((d = v_dot(r, g) / t) > 0.999f)
            {
                if ((e = (v_len(up->v) - dt)) > 0.0f)
                {
                    /* Scale the linear velocity. */

                    v_nrm(up->v, up->v);
                    v_scl(up->v, up->v, e);

                    /* Scale the angular velocity. */

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

                    up->v[0] = 0.0f;
                    up->v[1] = 0.0f;
                    up->v[2] = 0.0f;

                    (*m)++;
                }
            }
            else v_mad(up->v, v, g, tt);
        }
        else v_mad(up->v, v, g, tt);

        /* Test for collision. */

        for (c = 16; c > 0 && tt > 0; c--)
        {
            float st;
            int mi, ms;

            /* HACK: avoid stepping across path changes. */

            st = tt;

            for (mi = 0; mi < vary->mc; mi++)
            {
                struct v_move *mp = vary->mv + mi;
                struct v_path *pp = vary->pv + mp->pi;

                if (!pp->f)
                    continue;

                if (mp->tm + ms_peek(st) > pp->base->tm)
                    st = MS_TO_TIME(pp->base->tm - mp->tm);
            }

            /* Miss collisions if we reach the iteration limit. */

            if (c > 1)
                nt = sol_test_file(st, P, V, up, vary);
            else
                nt = tt;

            cmd.type       = CMD_STEP_SIMULATION;
            cmd.stepsim.dt = nt;
            sol_cmd_enq(&cmd);

            ms = ms_step(nt);

            sol_move_step(vary, nt, ms);
            sol_swch_step(vary, nt, ms);
            sol_ball_step(vary, nt);

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

            tt -= nt;
        }

        v_sub(a, up->v, a);

        sol_pendulum(up, a, g, dt);
    }

    return b;
}
Ejemplo n.º 22
0
Archivo: game.c Proyecto: rlk/neverball
void game_set_fly(float k)
{
    struct s_vary *fp = &file.vary;

    float  x[3] = { 1.f, 0.f, 0.f };
    float  y[3] = { 0.f, 1.f, 0.f };
    float  z[3] = { 0.f, 0.f, 1.f };
    float c0[3] = { 0.f, 0.f, 0.f };
    float p0[3] = { 0.f, 0.f, 0.f };
    float c1[3] = { 0.f, 0.f, 0.f };
    float p1[3] = { 0.f, 0.f, 0.f };
    float  v[3];

    if (!state)
        return;

    v_cpy(view_e[0], x);
    v_cpy(view_e[1], y);

    if (fp->base->zc > 0)
        v_sub(view_e[2], fp->uv[ball].p, fp->base->zv[0].p);
    else
        v_cpy(view_e[2], z);

    if (fabs(v_dot(view_e[1], view_e[2])) > 0.999)
        v_cpy(view_e[2], z);

    v_crs(view_e[0], view_e[1], view_e[2]);
    v_crs(view_e[2], view_e[0], view_e[1]);

    v_nrm(view_e[0], view_e[0]);
    v_nrm(view_e[2], view_e[2]);

    /* k = 0.0 view is at the ball. */

    if (fp->uc > 0)
    {
        v_cpy(c0, fp->uv[ball].p);
        v_cpy(p0, fp->uv[ball].p);
    }

    v_mad(p0, p0, view_e[1], view_dy);
    v_mad(p0, p0, view_e[2], view_dz);

    /* k = +1.0 view is s_view 0 */

    if (k >= 0 && fp->base->wc > 0)
    {
        v_cpy(p1, fp->base->wv[0].p);
        v_cpy(c1, fp->base->wv[0].q);
    }

    /* k = -1.0 view is s_view 1 */

    if (k <= 0 && fp->base->wc > 1)
    {
        v_cpy(p1, fp->base->wv[1].p);
        v_cpy(c1, fp->base->wv[1].q);
    }

    /* Interpolate the views. */

    v_sub(v, p1, p0);
    v_mad(view_p, p0, v, k * k);

    v_sub(v, c1, c0);
    v_mad(view_c, c0, v, k * k);

    /* Orthonormalize the view basis. */

    v_sub(view_e[2], view_p, view_c);
    v_crs(view_e[0], view_e[1], view_e[2]);
    v_crs(view_e[2], view_e[0], view_e[1]);
    v_nrm(view_e[0], view_e[0]);
    v_nrm(view_e[2], view_e[2]);

    view_a = V_DEG(fatan2f(view_e[2][0], view_e[2][2]));
}
Ejemplo n.º 23
0
int sol_lerp_cmd(struct s_lerp *fp, struct cmd_state *cs, const union cmd *cmd)
{
    struct l_ball (*uv)[2];
    struct l_ball *up;

    int idx, mi, i;
    int rc = 0;

    switch (cmd->type)
    {
    case CMD_MAKE_BALL:
        if ((uv = realloc(fp->uv, sizeof (*uv) * (fp->uc + 1))))
        {
            fp->uv = uv;

            /* Update varying state. */

            if (sol_vary_cmd(fp->vary, cs, cmd))
            {
                fp->uc++;
                rc = 1;
            }
        }
        break;

    case CMD_MOVE_PATH:
        if ((mi = cmd->movepath.mi) >= 0 && mi < fp->mc)
        {
            /* Be extra paranoid. */

            if ((idx = cmd->movepath.pi) >= 0 && idx < fp->vary->base->pc)
                fp->mv[mi][CURR].pi = idx;
        }
        break;

    case CMD_MOVE_TIME:
        if ((mi = cmd->movetime.mi) >= 0 && mi < fp->mc)
        {
            fp->mv[mi][CURR].t = cmd->movetime.t;
        }
        break;

    case CMD_BODY_PATH:
        /* Backward compatibility: update linear mover only. */

        if ((idx = cmd->bodypath.bi) >= 0 && idx < fp->vary->bc &&
            (mi = fp->vary->bv[idx].mi) >= 0)
        {
            /* Be EXTRA paranoid. */

            if ((idx = cmd->bodypath.pi) >= 0 && idx < fp->vary->base->pc)
                fp->mv[mi][CURR].pi = idx;
        }
        break;

    case CMD_BODY_TIME:
        /* Same as CMD_BODY_PATH. */

        if ((idx = cmd->bodytime.bi) >= 0 && idx < fp->vary->bc &&
            (mi = fp->vary->bv[idx].mi) >= 0)
        {
            fp->mv[mi][CURR].t = cmd->bodytime.t;
        }
        break;

    case CMD_BALL_RADIUS:
        fp->uv[cs->curr_ball][CURR].r = cmd->ballradius.r;
        break;

    case CMD_CLEAR_BALLS:
        free(fp->uv);
        fp->uv = NULL;
        fp->uc = 0;

        sol_vary_cmd(fp->vary, cs, cmd);

        break;

    case CMD_BALL_POSITION:
        up = &fp->uv[cs->curr_ball][CURR];
        v_cpy(up->p, cmd->ballpos.p);
        break;

    case CMD_BALL_BASIS:
        up = &fp->uv[cs->curr_ball][CURR];
        v_cpy(up->e[0], cmd->ballbasis.e[0]);
        v_cpy(up->e[1], cmd->ballbasis.e[1]);
        v_crs(up->e[2], up->e[0], up->e[1]);
        break;

    case CMD_BALL_PEND_BASIS:
        up = &fp->uv[cs->curr_ball][CURR];
        v_cpy(up->E[0], cmd->ballpendbasis.E[0]);
        v_cpy(up->E[1], cmd->ballpendbasis.E[1]);
        v_crs(up->E[2], up->E[0], up->E[1]);
        break;

    case CMD_STEP_SIMULATION:
        /*
         * Step each mover ahead. This  way we cut down on replay size
         * significantly  while  still  keeping  things in  sync  with
         * occasional CMD_MOVE_PATH and CMD_MOVE_TIME.
         */

        for (i = 0; i < fp->mc; i++)
        {
            struct l_move *mp = &fp->mv[i][CURR];

            if (mp->pi >= 0 && fp->vary->pv[mp->pi].f)
                mp->t += cmd->stepsim.dt;
        }
        break;

    default:
        break;
    }

    return rc;
}
Ejemplo n.º 24
0
Archivo: game.c Proyecto: rlk/neverball
void game_draw(int pose, float t)
{
    const float light_p[4] = { 8.f, 32.f, 8.f, 0.f };

    struct s_draw *fp = &file.draw;
    struct s_rend rend;

    float fov = FOV;

    if (!state)
        return;

    fp->shadow_ui = ball;

    game_shadow_conf(1);
    sol_draw_enable(&rend);

    if (jump_b) fov *= 2.0f * fabsf(jump_dt - 0.5f);

    video_push_persp(fov, 0.1f, FAR_DIST);
    glPushMatrix();
    {
        float T[16], M[16], v[3], c[3];

        /* In VR, move the view center up to keep the viewer level. */

        v_cpy(c, view_c);

        if (hmd_stat())
            c[1] += view_dy;

        video_calc_view(T, c, view_p, view_e[1]);
        m_xps(M, T);

        v_sub(v, c, view_p);

        glTranslatef(0.f, 0.f, -v_len(v));
        glMultMatrixf(M);
        glTranslatef(-c[0], -c[1], -c[2]);

        /* Center the skybox about the position of the camera. */

        glPushMatrix();
        {
            glTranslatef(view_p[0], view_p[1], view_p[2]);
            back_draw(&rend);
        }
        glPopMatrix();

        glEnable(GL_LIGHT0);
        glLightfv(GL_LIGHT0, GL_POSITION, light_p);

        /* Draw the floor. */

        sol_draw(fp, &rend, 0, 1);

        /* Draw the game elements. */

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        if (pose == 0)
        {
            game_draw_balls(&rend, fp->vary, T, t);
            game_draw_vect(&rend, fp->vary);
        }

        glDisable(GL_LIGHTING);
        glDepthMask(GL_FALSE);
        {
            game_draw_flags(&rend, fp->base);
            game_draw_beams(&rend, fp->base, fp->vary);
        }
        glDepthMask(GL_TRUE);
        glEnable(GL_LIGHTING);
    }
    glPopMatrix();
    video_pop_matrix();

    sol_draw_disable(&rend);
    game_shadow_conf(0);
}
Ejemplo n.º 25
0
Archivo: game.c Proyecto: rlk/neverball
void game_update_view(float dt)
{
    const float y[3] = { 0.f, 1.f, 0.f };

    float dy;
    float dz;
    float k;
    float e[3];
    float d[3];
    float s = 2.f * dt;

    if (!state)
        return;

    /* Center the view about the ball. */

    v_cpy(view_c, file.vary.uv[ball].p);
    v_inv(view_v, file.vary.uv[ball].v);

    switch (config_get_d(CONFIG_CAMERA))
    {
    case 2:
        /* Camera 2: View vector is given by view angle. */

        view_e[2][0] = fsinf(V_RAD(view_a));
        view_e[2][1] = 0.f;
        view_e[2][2] = fcosf(V_RAD(view_a));

        s = 1.f;
        break;

    default:
        /* View vector approaches the ball velocity vector. */

        v_mad(e, view_v, y, v_dot(view_v, y));
        v_inv(e, e);

        k = v_dot(view_v, view_v);

        v_sub(view_e[2], view_p, view_c);
        v_mad(view_e[2], view_e[2], view_v, k * dt * 0.1f);
    }

    /* Orthonormalize the basis of the view in its new position. */

    v_crs(view_e[0], view_e[1], view_e[2]);
    v_crs(view_e[2], view_e[0], view_e[1]);
    v_nrm(view_e[0], view_e[0]);
    v_nrm(view_e[2], view_e[2]);

    /* The current view (dy, dz) approaches the ideal (view_dy, view_dz). */

    v_sub(d, view_p, view_c);

    dy = v_dot(view_e[1], d);
    dz = v_dot(view_e[2], d);

    dy += (view_dy - dy) * s;
    dz += (view_dz - dz) * s;

    /* Compute the new view position. */

    view_p[0] = view_p[1] = view_p[2] = 0.f;

    v_mad(view_p, view_c, view_e[1], dy);
    v_mad(view_p, view_p, view_e[2], dz);

    view_a = V_DEG(fatan2f(view_e[2][0], view_e[2][2]));
}
Ejemplo n.º 26
0
static void game_run_cmd(const union cmd *cmd)
{
    if (gd.state)
    {
        struct game_view *view = &gl.view[CURR];
        struct game_tilt *tilt = &gl.tilt[CURR];

        struct s_vary *vary = &gd.vary;
        struct v_item *hp;

        float v[4];
        float dt;

        int idx;

        if (cs.next_update)
        {
            game_lerp_copy(&gl);
            cs.next_update = 0;
        }

        switch (cmd->type)
        {
        case CMD_END_OF_UPDATE:
            cs.got_tilt_axes = 0;
            cs.next_update = 1;

            if (cs.first_update)
            {
                game_lerp_copy(&gl);
                /* Hack to sync state before the next update. */
                game_lerp_apply(&gl, &gd);
                cs.first_update = 0;
                break;
            }

            /* Compute gravity for particle effects. */

            if (status == GAME_GOAL)
                game_tilt_grav(v, GRAVITY_UP, tilt);
            else
                game_tilt_grav(v, GRAVITY_DN, tilt);

            /* Step particle, goal and jump effects. */

            if (cs.ups > 0)
            {
                dt = 1.0f / cs.ups;

                if (gd.goal_e && gl.goal_k[CURR] < 1.0f)
                    gl.goal_k[CURR] += dt;

                if (gd.jump_b)
                {
                    gl.jump_dt[CURR] += dt;

                    if (gl.jump_dt[PREV] >= 1.0f)
                        gd.jump_b = 0;
                }

                part_step(v, dt);
            }

            break;

        case CMD_MAKE_BALL:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_MAKE_ITEM:
            /* Allocate and initialize a new item. */

            if ((hp = realloc(vary->hv, sizeof (*hp) * (vary->hc + 1))))
            {
                vary->hv = hp;
                hp = &vary->hv[vary->hc];
                vary->hc++;

                memset(hp, 0, sizeof (*hp));

                v_cpy(hp->p, cmd->mkitem.p);

                hp->t = cmd->mkitem.t;
                hp->n = cmd->mkitem.n;
            }

            break;

        case CMD_PICK_ITEM:
            /* Set up particle effects and discard the item. */

            if ((idx = cmd->pkitem.hi) >= 0 && idx < vary->hc)
            {
                hp = &vary->hv[idx];

                item_color(hp, v);
                part_burst(hp->p, v);

                hp->t = ITEM_NONE;
            }
            break;

        case CMD_TILT_ANGLES:
            if (!cs.got_tilt_axes)
            {
                /*
                 * 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.
                 */

                game_tilt_axes(tilt, view->e);
            }

            tilt->rx = cmd->tiltangles.x;
            tilt->rz = cmd->tiltangles.z;
            break;

        case CMD_SOUND:
            /* Play the sound. */

            if (cmd->sound.n)
                audio_play(cmd->sound.n, cmd->sound.a);

            break;

        case CMD_TIMER:
            timer = cmd->timer.t;
            break;

        case CMD_STATUS:
            status = cmd->status.t;
            break;

        case CMD_COINS:
            coins = cmd->coins.n;
            break;

        case CMD_JUMP_ENTER:
            gd.jump_b  = 1;
            gd.jump_e  = 0;
            gl.jump_dt[PREV] = 0.0f;
            gl.jump_dt[CURR] = 0.0f;
            break;

        case CMD_JUMP_EXIT:
            gd.jump_e = 1;
            break;

        case CMD_MOVE_PATH:
        case CMD_MOVE_TIME:
        case CMD_BODY_PATH:
        case CMD_BODY_TIME:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_GOAL_OPEN:
            /*
             * Enable the goal and make sure it's fully visible if
             * this is the first update.
             */

            if (!gd.goal_e)
            {
                gd.goal_e = 1;
                gl.goal_k[CURR] = cs.first_update ? 1.0f : 0.0f;
            }
            break;

        case CMD_SWCH_ENTER:
            if ((idx = cmd->swchenter.xi) >= 0 && idx < vary->xc)
                vary->xv[idx].e = 1;
            break;

        case CMD_SWCH_TOGGLE:
            if ((idx = cmd->swchtoggle.xi) >= 0 && idx < vary->xc)
                vary->xv[idx].f = !vary->xv[idx].f;
            break;

        case CMD_SWCH_EXIT:
            if ((idx = cmd->swchexit.xi) >= 0 && idx < vary->xc)
                vary->xv[idx].e = 0;
            break;

        case CMD_UPDATES_PER_SECOND:
            cs.ups = cmd->ups.n;
            break;

        case CMD_BALL_RADIUS:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_CLEAR_ITEMS:
            free(vary->hv);
            vary->hv = NULL;
            vary->hc = 0;
            break;

        case CMD_CLEAR_BALLS:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_BALL_POSITION:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_BALL_BASIS:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_BALL_PEND_BASIS:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_VIEW_POSITION:
            v_cpy(view->p, cmd->viewpos.p);
            break;

        case CMD_VIEW_CENTER:
            v_cpy(view->c, cmd->viewcenter.c);
            break;

        case CMD_VIEW_BASIS:
            v_cpy(view->e[0], cmd->viewbasis.e[0]);
            v_cpy(view->e[1], cmd->viewbasis.e[1]);
            v_crs(view->e[2], view->e[0], view->e[1]);
            break;

        case CMD_CURRENT_BALL:
            if ((idx = cmd->currball.ui) >= 0 && idx < vary->uc)
                cs.curr_ball = idx;
            break;

        case CMD_PATH_FLAG:
            if ((idx = cmd->pathflag.pi) >= 0 && idx < vary->pc)
                vary->pv[idx].f = cmd->pathflag.f;
            break;

        case CMD_STEP_SIMULATION:
            sol_lerp_cmd(&gl.lerp, &cs, cmd);
            break;

        case CMD_MAP:
            /*
             * Note a version (mis-)match between the loaded map and what
             * the server has. (This doesn't actually load a map.)
             */
            game_compat_map = (version.x == cmd->map.version.x);
            break;

        case CMD_TILT_AXES:
            cs.got_tilt_axes = 1;
            v_cpy(tilt->x, cmd->tiltaxes.x);
            v_cpy(tilt->z, cmd->tiltaxes.z);
            break;

        case CMD_NONE:
        case CMD_MAX:
            break;
        }
    }
}
Ejemplo n.º 27
0
static int game_step(const float g[3], float dt, int bt)
{
    if (server_state)
    {
        float h[3];

        /* Smooth jittery or discontinuous input. */

        tilt.rx += (input_get_x() - tilt.rx) * dt / input_get_s();
        tilt.rz += (input_get_z() - tilt.rz) * dt / input_get_s();

        game_tilt_axes(&tilt, view.e);

        game_cmd_tiltaxes();
        game_cmd_tiltangles();

        grow_step(&vary, dt);

        game_tilt_grav(h, g, &tilt);

        if (jump_b > 0)
        {
            jump_dt += dt;

            /* Handle a jump. */

            if (jump_dt >= 0.5f)
            {
                /* Translate view at the exact instant of the jump. */

                if (jump_b == 1)
                {
                    float dp[3];

                    v_sub(dp,     jump_p, vary.uv->p);
                    v_add(view.p, view.p, dp);

                    jump_b = 2;
                }

                /* Translate ball and hold it at the destination. */

                v_cpy(vary.uv->p, jump_p);
            }

            if (jump_dt >= 1.0f)
                jump_b = 0;
        }
        else
        {
            /* Run the sim. */

            float b = sol_step(&vary, h, dt, 0, NULL);

            /* Mix the sound of a ball bounce. */

            if (b > 0.5f)
            {
                float k = (b - 0.5f) * 2.0f;

                if (got_orig)
                {
                    if      (vary.uv->r > grow_orig) audio_play(AUD_BUMPL, k);
                    else if (vary.uv->r < grow_orig) audio_play(AUD_BUMPS, k);
                    else                             audio_play(AUD_BUMPM, k);
                }
                else audio_play(AUD_BUMPM, k);
            }
        }

        game_cmd_updball();

        game_update_view(dt);
        game_update_time(dt, bt);

        return game_update_state(bt);
    }
    return GAME_NONE;
}
Ejemplo n.º 28
0
int sol_load_vary(struct s_vary *fp, struct s_base *base)
{
    int i;

    memset(fp, 0, sizeof (*fp));

    fp->base = base;

    if (fp->base->pc)
    {
        fp->pv = (struct v_path*)calloc(fp->base->pc, sizeof (*fp->pv));
        fp->pc = fp->base->pc;

        for (i = 0; i < fp->base->pc; i++)
        {
            struct v_path *pp = fp->pv + i;
            struct b_path *pq = fp->base->pv + i;

            pp->base = pq;
            pp->f    = pq->f;
        }
    }

    if (fp->base->bc)
    {
        struct alloc mv;

        fp->bv = (struct v_body*)calloc(fp->base->bc, sizeof (*fp->bv));
        fp->bc = fp->base->bc;

        alloc_new(&mv, sizeof (*fp->mv), (void **) &fp->mv, &fp->mc);

        for (i = 0; i < fp->base->bc; i++)
        {
            struct b_body *bbody = fp->base->bv + i;
            struct v_body *vbody = fp->bv + i;
            struct v_move *vmove;

            vbody->base = bbody;

            vbody->mi = -1;
            vbody->mj = -1;

            if (bbody->pi >= 0 && (vmove = (struct v_move*)alloc_add(&mv)))
            {
                memset(vmove, 0, sizeof (*vmove));

                vbody->mi = fp->mc - 1;
                vmove->pi = bbody->pi;
            }

            if (bbody->pj == bbody->pi)
            {
                vbody->mj = vbody->mi;
            }
            else if (bbody->pj >= 0 && (vmove = (struct v_move*)alloc_add(&mv)))
            {
                memset(vmove, 0, sizeof (*vmove));

                vbody->mj = fp->mc - 1;
                vmove->pi = bbody->pj;
            }
        }
    }

    if (fp->base->hc)
    {
        fp->hv = (struct v_item*)calloc(fp->base->hc, sizeof (*fp->hv));
        fp->hc = fp->base->hc;

        for (i = 0; i < fp->base->hc; i++)
        {
            struct v_item *hp = fp->hv + i;
            struct b_item *hq = fp->base->hv + i;

            v_cpy(hp->p, hq->p);

            hp->t = hq->t;
            hp->n = hq->n;
        }
    }

    if (fp->base->xc)
    {
        fp->xv = (struct v_swch*)calloc(fp->base->xc, sizeof (*fp->xv));
        fp->xc = fp->base->xc;

        for (i = 0; i < fp->base->xc; i++)
        {
            struct v_swch *xp = fp->xv + i;
            struct b_swch *xq = fp->base->xv + i;

            xp->base = xq;
            xp->t    = xq->t;
            xp->tm   = xq->tm;
            xp->f    = xq->f;
        }
    }

    if (fp->base->uc)
    {
        fp->uv = (struct v_ball*)calloc(fp->base->uc, sizeof (*fp->uv));
        fp->uc = fp->base->uc;

        for (i = 0; i < fp->base->uc; i++)
        {
            struct v_ball *up = fp->uv + i;
            struct b_ball *uq = fp->base->uv + i;

            v_cpy(up->p, uq->p);

            up->r = uq->r;

            up->E[0][0] = up->e[0][0] = 1.0f;
            up->E[0][1] = up->e[0][1] = 0.0f;
            up->E[0][2] = up->e[0][2] = 0.0f;

            up->E[1][0] = up->e[1][0] = 0.0f;
            up->E[1][1] = up->e[1][1] = 1.0f;
            up->E[1][2] = up->e[1][2] = 0.0f;

            up->E[2][0] = up->e[2][0] = 0.0f;
            up->E[2][1] = up->e[2][1] = 0.0f;
            up->E[2][2] = up->e[2][2] = 1.0f;
        }
    }

    return 1;
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
-1
static void game_update_view(float dt)
{
    float dc = view.dc * (jump_b > 0 ? 2.0f * fabsf(jump_dt - 0.5f) : 1.0f);
    float da = input_get_r() * dt * 90.0f;
    float k;

    float M[16], v[3], Y[3] = { 0.0f, 1.0f, 0.0f };
    float view_v[3];

    float spd = (float) cam_speed(input_get_c()) / 1000.0f;

    /* Track manual rotation time. */

    if (da == 0.0f)
    {
        if (view_time < 0.0f)
        {
            /* Transition time is influenced by activity time. */

            view_fade = CLAMP(VIEW_FADE_MIN, -view_time, VIEW_FADE_MAX);
            view_time = 0.0f;
        }

        /* Inactivity. */

        view_time += dt;
    }
    else
    {
        if (view_time > 0.0f)
        {
            view_fade = 0.0f;
            view_time = 0.0f;
        }

        /* Activity (yes, this is negative). */

        view_time -= dt;
    }

    /* Center the view about the ball. */

    v_cpy(view.c, vary.uv->p);

    view_v[0] = -vary.uv->v[0];
    view_v[1] =  0.0f;
    view_v[2] = -vary.uv->v[2];

    /* Compute view vector. */

    if (spd >= 0.0f)
    {
        /* Viewpoint chases ball position. */

        if (da == 0.0f)
        {
            float s;

            v_sub(view.e[2], view.p, view.c);
            v_nrm(view.e[2], view.e[2]);

            /* Gradually restore view vector convergence rate. */

            s = fpowf(view_time, 3.0f) / fpowf(view_fade, 3.0f);
            s = CLAMP(0.0f, s, 1.0f);

            v_mad(view.e[2], view.e[2], view_v, v_len(view_v) * spd * s * dt);
        }
    }
    else
    {
        /* View vector is given by view angle. */

        view.e[2][0] = fsinf(V_RAD(view.a));
        view.e[2][1] = 0.0;
        view.e[2][2] = fcosf(V_RAD(view.a));
    }

    /* Apply manual rotation. */

    if (da != 0.0f)
    {
        m_rot(M, Y, V_RAD(da));
        m_vxfm(v, M, view.e[2]);
        v_cpy(view.e[2], v);
    }

    /* Orthonormalize the new view reference frame. */

    v_crs(view.e[0], view.e[1], view.e[2]);
    v_crs(view.e[2], view.e[0], view.e[1]);
    v_nrm(view.e[0], view.e[0]);
    v_nrm(view.e[2], view.e[2]);

    /* Compute the new view position. */

    k = 1.0f + v_dot(view.e[2], view_v) / 10.0f;

    view_k = view_k + (k - view_k) * dt;

    if (view_k < 0.5) view_k = 0.5;

    v_scl(v,    view.e[1], view.dp * view_k);
    v_mad(v, v, view.e[2], view.dz * view_k);
    v_add(view.p, v, vary.uv->p);

    /* Compute the new view center. */

    v_cpy(view.c, vary.uv->p);
    v_mad(view.c, view.c, view.e[1], dc);

    /* Note the current view angle. */

    view.a = V_DEG(fatan2f(view.e[2][0], view.e[2][2]));

    game_cmd_updview();
}