Exemplo n.º 1
0
static
__forceinline
float calcRelVel(const float4& l0, const float4& l1, const float4& a0, const float4& a1,
                 const float4& linVel0, const float4& angVel0, const float4& linVel1, const float4& angVel1)
{
    return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
}
Exemplo n.º 2
0
float ClothSimulation::calcVolume( const float4* v, const int4* t, int n )
{
	float vol = 0;
	for(int i=0; i<n; i++)
	{
		const int4& tri = t[i];
		float4 c = cross3(v[tri.y], v[tri.x]);
		vol += dot3F4( c, v[tri.z] );
	}
	return fabs( vol/6.f );
}
int collideStraight(const ConvexHeightField* shapeA,const ConvexHeightField* shapeB,
                    const float4& bodyApos, Quaternion& bodyAquat,const float4& bodyBpos,const Quaternion& bodyBquat,
                    ContactPoint4* contactsOut, int& numContacts, int contactCapacity,
                    float collisionMargin )
{
//	Stopwatch sw;

    Transform trA;
    trA = trSetTransform(bodyApos,bodyAquat);
    Transform trB;
    trB = trSetTransform(bodyBpos, bodyBquat);

    Transform B2A;
    {
        Transform invTrA = trInvert( trA );
        B2A = trMul( invTrA, trB );
    }

    int nContacts = 0;
    {   // testB against A
        float4 p[ConvexHeightField::HEIGHT_RES*ConvexHeightField::HEIGHT_RES*6];
        int nHits = 0;

        const float4* pInB = shapeB->getSamplePoints();

        float4 baInB = qtInvRotate( bodyBquat, bodyApos - bodyBpos );
        if( shapeA->m_type == CollisionShape::SHAPE_HEIGHT_FIELD )
            baInB = make_float4(0,0,0,0);

//		sw.start();
        for(int iface=0; iface<6; iface++)
        {
            Aabb aabb = shapeB->m_faceAabbs[iface];

            aabb.transform( B2A.m_translation, B2A.m_rotation );

            if( !shapeA->m_aabb.overlaps( aabb ) ) continue;

            for(int ip=0; ip<ConvexHeightField::HEIGHT_RES*ConvexHeightField::HEIGHT_RES; ip++)
            {
                int i = iface*ConvexHeightField::HEIGHT_RES*ConvexHeightField::HEIGHT_RES+ip;

                if( dot3F4( baInB, pInB[i] ) < 0.f ) continue;

                float4 pInA = trMul1( B2A, pInB[i] );

                if( shapeA->m_aabb.overlaps( pInA ) )
                {
//					Stopwatch sw1;
//					sw1.start();
                    float dist = shapeA->queryDistance( pInA );
//					sw1.stop();
//					m_times[TIME_SAMPLE] += sw1.getMs();

                    if( dist < collisionMargin )
                    {
                        p[nHits] = make_float4(pInA.x, pInA.y, pInA.z, dist);
                        nHits++;
                    }
                }
            }
        }
//		sw.stop();
//		m_times[TIME_TEST] += sw.getMs();

//		sw.start();
        if( nHits )
        {
            float4 ab = bodyBpos - bodyApos;
            ab = qtInvRotate( bodyAquat, ab );
            if( shapeA->m_type == CollisionShape::SHAPE_HEIGHT_FIELD )
            {
                //todo.	sample normal from height field but just fake here
                ab = make_float4(0,1,0,0);
            }

            int cIdx[4];
            float4 center;

            nContacts = extractManifold( p, nHits, ab, center, cIdx );

            float4 contactNormal;
            {
                shapeA->queryDistanceWithNormal( center, contactNormal );
                contactNormal = normalize3( contactNormal );

//				u32 cmp = u8vCompress( contactNormal );
//				contactNormal = make_float4( u8vGetX(cmp), u8vGetY(cmp), u8vGetZ(cmp), 0 );
            }

            int writeIdx = atomAdd( &numContacts, 1 );
            if( writeIdx+1 < contactCapacity )
            {
                ContactPoint4& c = contactsOut[writeIdx];
                nContacts = min2( nContacts, 4 );
                for(int i=0; i<nContacts; i++)
                {
                    c.m_worldPos[i] = transform( p[cIdx[i]], bodyApos, bodyAquat );
                    c.m_worldPos[i].w = max2( p[cIdx[i]].w - collisionMargin, -2*collisionMargin );
                }
                c.m_worldNormal = normalize3( qtRotate( bodyAquat, contactNormal ) );
                c.m_restituitionCoeff = 0.f;
                c.m_frictionCoeff = 0.7f;
                //c.m_bodyAPtr = (void*)bodyAIdx;
                //c.m_bodyBPtr = (void*)bodyBIdx;
                c.getNPoints() = nContacts;
            }
        }
//		sw.stop();
//		m_times[TIME_MANIFOLD] += sw.getMs();
    }

    return nContacts;
}
int extractManifold(const float4* p, int nPoints, float4& nearNormal, float4& centerOut,
                    int contactIdx[4])
{
    if( nPoints == 0 ) return 0;

    nPoints = min2( nPoints, 64 );

    float4 center = make_float4(0.f);
    {
        float4 v[64];
        memcpy( v, p, nPoints*sizeof(float4) );
        PARALLEL_SUM( v, nPoints );
        center = v[0]/(float)nPoints;
    }

    centerOut = center;

    {   //	sample 4 directions
        if( nPoints < 4 )
        {
            for(int i=0; i<nPoints; i++) contactIdx[i] = i;
            return nPoints;
        }

        float4 aVector = p[0] - center;
        float4 u = cross3( nearNormal, aVector );
        float4 v = cross3( nearNormal, u );
        u = normalize3( u );
        v = normalize3( v );

        int idx[4];

        float2 max00 = make_float2(0,FLT_MAX);
        {
            float4 dir0 = u;
            float4 dir1 = -u;
            float4 dir2 = v;
            float4 dir3 = -v;

            //	idx, distance
            {
                {
                    int4 a[64];
                    for(int ie = 0; ie<nPoints; ie++ )
                    {
                        float4 f;
                        float4 r = p[ie]-center;
                        f.x = dot3F4( dir0, r );
                        f.y = dot3F4( dir1, r );
                        f.z = dot3F4( dir2, r );
                        f.w = dot3F4( dir3, r );

                        a[ie].x = ((*(u32*)&f.x) & 0xffffff00);
                        a[ie].x |= (0xff & ie);

                        a[ie].y = ((*(u32*)&f.y) & 0xffffff00);
                        a[ie].y |= (0xff & ie);

                        a[ie].z = ((*(u32*)&f.z) & 0xffffff00);
                        a[ie].z |= (0xff & ie);

                        a[ie].w = ((*(u32*)&f.w) & 0xffffff00);
                        a[ie].w |= (0xff & ie);
                    }

                    for(int ie=0; ie<nPoints; ie++)
                    {
                        a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;
                        a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;
                        a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;
                        a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;
                    }

                    idx[0] = (int)a[0].x & 0xff;
                    idx[1] = (int)a[0].y & 0xff;
                    idx[2] = (int)a[0].z & 0xff;
                    idx[3] = (int)a[0].w & 0xff;
                }
            }

            {
                float2 h[64];
                PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );
                REDUCE_MIN( h, nPoints );
                max00 = h[0];
            }
        }

        contactIdx[0] = idx[0];
        contactIdx[1] = idx[1];
        contactIdx[2] = idx[2];
        contactIdx[3] = idx[3];

//		if( max00.y < 0.0f )
//			contactIdx[0] = (int)max00.x;

        std::sort( contactIdx, contactIdx+4 );

        return 4;
    }
}
Exemplo n.º 5
0
static
__inline
void solveFriction(Constraint4& cs,
                   const float4& posA, float4& linVelA, float4& angVelA, float invMassA, const Matrix3x3& invInertiaA,
                   const float4& posB, float4& linVelB, float4& angVelB, float invMassB, const Matrix3x3& invInertiaB,
                   float maxRambdaDt[4], float minRambdaDt[4])
{
    if( cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0 ) return;
    const float4& center = cs.m_center;

    float4 n = -cs.m_linear;

    float4 tangent[2];
#if 1
    btPlaneSpace1 (&n, &tangent[0],&tangent[1]);
#else
    float4 r = cs.m_worldPos[0]-center;
    tangent[0] = cross3( n, r );
    tangent[1] = cross3( tangent[0], n );
    tangent[0] = normalize3( tangent[0] );
    tangent[1] = normalize3( tangent[1] );
#endif

    float4 angular0, angular1, linear;
    float4 r0 = center - posA;
    float4 r1 = center - posB;
    for(int i=0; i<2; i++)
    {
        setLinearAndAngular( tangent[i], r0, r1, linear, angular0, angular1 );
        float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
                                    linVelA, angVelA, linVelB, angVelB );
        rambdaDt *= cs.m_fJacCoeffInv[i];

        {
            float prevSum = cs.m_fAppliedRambdaDt[i];
            float updated = prevSum;
            updated += rambdaDt;
            updated = max2( updated, minRambdaDt[i] );
            updated = min2( updated, maxRambdaDt[i] );
            rambdaDt = updated - prevSum;
            cs.m_fAppliedRambdaDt[i] = updated;
        }

        float4 linImp0 = invMassA*linear*rambdaDt;
        float4 linImp1 = invMassB*(-linear)*rambdaDt;
        float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
        float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
#ifdef _WIN32
        btAssert(_finite(linImp0.x));
        btAssert(_finite(linImp1.x));
#endif
        linVelA += linImp0;
        angVelA += angImp0;
        linVelB += linImp1;
        angVelB += angImp1;
    }

    {   //	angular damping for point constraint
        float4 ab = normalize3( posB - posA );
        float4 ac = normalize3( center - posA );
        if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
        {
            float angNA = dot3F4( n, angVelA );
            float angNB = dot3F4( n, angVelB );

            angVelA -= (angNA*0.1f)*n;
            angVelB -= (angNB*0.1f)*n;
        }
    }
}