Exemple #1
0
static void state_matrix(double *M, const state *s)
{
    double T[16], R[16], p[3];

    vneg(p, s->p);

    mtranslate(T, p);
    meuler    (R, s->e);
    mmultiply (M, R, T);
}
Exemple #2
0
/*
 * Function: ri_bem_set
 *
 *   Setups a beam structure.
 *
 *
 * Parameters:
 *
 *   beam   - Pointer to the beam to be set up. 
 *   org    - Origin of beam.
 *   dir[4] - Corner rays of beam. 
 *
 *
 * Returns:
 *
 *   0 if OK, otherwise if err
 */
int
ri_beam_set(
    ri_beam_t   *beam,      /* [inout]  */
    ri_vector_t  org,
    ri_vector_t  dir[4])
{
    int        i, j;
    int        mask;
    int        dominant_axis;
    int        zeros;
    ri_float_t maxval;  

    beam->d     = 1024.0;
    beam->t_max = RI_INFINITY;

    /*
     * Check if beam's directions lie in same quadrant.
     */
    for (i = 0; i < 3; i++) {

        zeros = 0;
        mask  = 0;

        for (j = 0; j < 4; j++) {
            if (fabs(dir[j][i]) < RI_EPS) {
                zeros++;
            } else {
                mask  += (dir[j][i] <  0.0) ? 1 : -1;
            }
        }

        if ( (mask != -(4 - zeros)) && (mask != (4 - zeros)) ) {

            /* FIXME:
             * split beam so that subdivided beam has same sign.
             */
            fprintf(stderr, "TODO: Beam's dir does not have same sign.\n");

            for (j = 0; j < 4; j++) {
                fprintf(stderr, "      dir[%d] = %f, %f, %f\n", j,
                    dir[j][0], dir[j][1], dir[j][2]);
            }

            return -1;

        }

    }

    vcpy( beam->org,    org    );

    /*
     * Find dominant plane. Use dir[0]
     */
    maxval        = fabs(dir[0][0]);
    dominant_axis = 0;
    if ( (maxval < fabs(dir[0][1])) ) {
        maxval        = fabs(dir[0][0]);
        dominant_axis = 1;
    }
    if ( (maxval < fabs(dir[0][2])) ) {
        maxval        = fabs(dir[0][2]);
        dominant_axis = 2;
    }
         
    beam->dominant_axis = dominant_axis;

    /*
     * Precompute sign of direction.
     * We know all 4 directions has same sign, thus dir[0] is used to
     * get sign of direction for each axis.
     */
    beam->dirsign[0] = (dir[0][0] < 0.0) ? 1 : 0;
    beam->dirsign[1] = (dir[0][1] < 0.0) ? 1 : 0;
    beam->dirsign[2] = (dir[0][2] < 0.0) ? 1 : 0;


    /*
     * Project beam dir onto axis-alied plane.
     */
    {

        ri_vector_t normals[3] = {
            { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 } };
        ri_vector_t normal;
        ri_float_t  t;
        ri_float_t  k;

        vcpy( normal, normals[beam->dominant_axis] );
        
        if (beam->dirsign[beam->dominant_axis]) {
            vneg( normal );
        }


        for (i = 0; i < 4; i++) {

            t = vdot( dir[i], normal );
            
            if (fabs(t) > RI_EPS) {
                k = beam->d / t;
            } else {
                k = 1.0;
            }

            beam->dir[i][0] = k * dir[i][0];
            beam->dir[i][1] = k * dir[i][1];
            beam->dir[i][2] = k * dir[i][2];
            
        }

    }


    /*
     * Precompute inverse of direction
     */
    for (i = 0; i < 4; i++) {
        beam->invdir[i][0] = safeinv( beam->dir[i][0], RI_EPS, RI_FLT_MAX );
        beam->invdir[i][1] = safeinv( beam->dir[i][1], RI_EPS, RI_FLT_MAX );
        beam->invdir[i][2] = safeinv( beam->dir[i][2], RI_EPS, RI_FLT_MAX );
    }

    /*
     * Precompute normal plane of beam frustum
     */
    vcross( beam->normal[0], beam->dir[1], beam->dir[0] );
    vcross( beam->normal[1], beam->dir[2], beam->dir[1] );
    vcross( beam->normal[2], beam->dir[3], beam->dir[2] );
    vcross( beam->normal[3], beam->dir[0], beam->dir[3] );

    beam->is_tetrahedron = 0;

    return 0;   /* OK   */
}
Exemple #3
0
static void
cpArbiterApplyImpulse_NEON(cpArbiter *arb)
{
    cpBody *a = arb->body_a;
    cpBody *b = arb->body_b;
    cpFloatx2_t surface_vr = vld((cpFloat_t *)&arb->surface_vr);
    cpFloatx2_t n = vld((cpFloat_t *)&arb->n);
    cpFloat_t friction = arb->u;

    int numContacts = arb->count;
    struct cpContact *contacts = arb->contacts;
    for(int i=0; i<numContacts; i++) {
        struct cpContact *con = contacts + i;
        cpFloatx2_t r1 = vld((cpFloat_t *)&con->r1);
        cpFloatx2_t r2 = vld((cpFloat_t *)&con->r2);

        cpFloatx2_t perp = vmake(-1.0, 1.0);
        cpFloatx2_t r1p = vmul(vrev(r1), perp);
        cpFloatx2_t r2p = vmul(vrev(r2), perp);

        cpFloatx2_t vBias_a = vld((cpFloat_t *)&a->v_bias);
        cpFloatx2_t vBias_b = vld((cpFloat_t *)&b->v_bias);
        cpFloatx2_t wBias = vmake(a->w_bias, b->w_bias);

        cpFloatx2_t vb1 = vadd(vBias_a, vmul_n(r1p, vget_lane(wBias, 0)));
        cpFloatx2_t vb2 = vadd(vBias_b, vmul_n(r2p, vget_lane(wBias, 1)));
        cpFloatx2_t vbr = vsub(vb2, vb1);

        cpFloatx2_t v_a = vld((cpFloat_t *)&a->v);
        cpFloatx2_t v_b = vld((cpFloat_t *)&b->v);
        cpFloatx2_t w = vmake(a->w, b->w);
        cpFloatx2_t v1 = vadd(v_a, vmul_n(r1p, vget_lane(w, 0)));
        cpFloatx2_t v2 = vadd(v_b, vmul_n(r2p, vget_lane(w, 1)));
        cpFloatx2_t vr = vsub(v2, v1);

        cpFloatx2_t vbn_vrn = vpadd(vmul(vbr, n), vmul(vr, n));

        cpFloatx2_t v_offset = vmake(con->bias, -con->bounce);
        cpFloatx2_t jOld = vmake(con->jBias, con->jnAcc);
        cpFloatx2_t jbn_jn = vmul_n(vsub(v_offset, vbn_vrn), con->nMass);
        jbn_jn = vmax(vadd(jOld, jbn_jn), vdup_n(0.0));
        cpFloatx2_t jApply = vsub(jbn_jn, jOld);

        cpFloatx2_t t = vmul(vrev(n), perp);
        cpFloatx2_t vrt_tmp = vmul(vadd(vr, surface_vr), t);
        cpFloatx2_t vrt = vpadd(vrt_tmp, vrt_tmp);

        cpFloatx2_t jtOld = {};
        jtOld = vset_lane(con->jtAcc, jtOld, 0);
        cpFloatx2_t jtMax = vrev(vmul_n(jbn_jn, friction));
        cpFloatx2_t jt = vmul_n(vrt, -con->tMass);
        jt = vmax(vneg(jtMax), vmin(vadd(jtOld, jt), jtMax));
        cpFloatx2_t jtApply = vsub(jt, jtOld);

        cpFloatx2_t i_inv = vmake(-a->i_inv, b->i_inv);
        cpFloatx2_t nperp = vmake(1.0, -1.0);

        cpFloatx2_t jBias = vmul_n(n, vget_lane(jApply, 0));
        cpFloatx2_t jBiasCross = vmul(vrev(jBias), nperp);
        cpFloatx2_t biasCrosses = vpadd(vmul(r1, jBiasCross), vmul(r2, jBiasCross));
        wBias = vadd(wBias, vmul(i_inv, biasCrosses));

        vBias_a = vsub(vBias_a, vmul_n(jBias, a->m_inv));
        vBias_b = vadd(vBias_b, vmul_n(jBias, b->m_inv));

        cpFloatx2_t j = vadd(vmul_n(n, vget_lane(jApply, 1)), vmul_n(t, vget_lane(jtApply, 0)));
        cpFloatx2_t jCross = vmul(vrev(j), nperp);
        cpFloatx2_t crosses = vpadd(vmul(r1, jCross), vmul(r2, jCross));
        w = vadd(w, vmul(i_inv, crosses));

        v_a = vsub(v_a, vmul_n(j, a->m_inv));
        v_b = vadd(v_b, vmul_n(j, b->m_inv));

        // TODO would moving these earlier help pipeline them better?
        vst((cpFloat_t *)&a->v_bias, vBias_a);
        vst((cpFloat_t *)&b->v_bias, vBias_b);
        vst_lane((cpFloat_t *)&a->w_bias, wBias, 0);
        vst_lane((cpFloat_t *)&b->w_bias, wBias, 1);

        vst((cpFloat_t *)&a->v, v_a);
        vst((cpFloat_t *)&b->v, v_b);
        vst_lane((cpFloat_t *)&a->w, w, 0);
        vst_lane((cpFloat_t *)&b->w, w, 1);

        vst_lane((cpFloat_t *)&con->jBias, jbn_jn, 0);
        vst_lane((cpFloat_t *)&con->jnAcc, jbn_jn, 1);
        vst_lane((cpFloat_t *)&con->jtAcc, jt, 0);
    }
}