public override void ProcessCollision (CollisionObject body0,CollisionObject body1,DispatcherInfo dispatchInfo,ManifoldResult resultOut)
        {
	        if (m_manifoldPtr == null)
	        {
		        //swapped?
		        m_manifoldPtr = m_dispatcher.GetNewManifold(body0,body1);
		        m_ownManifold = true;
	        }
	        resultOut.SetPersistentManifold(m_manifoldPtr);

	        //comment-out next line to test multi-contact generation
	        //resultOut.getPersistentManifold().clearManifold();


	        ConvexShape min0 = (ConvexShape)(body0.GetCollisionShape());
	        ConvexShape min1 = (ConvexShape)(body1.GetCollisionShape());

	        Vector3  normalOnB = Vector3.Zero;
	        Vector3  pointOnBWorld = Vector3.Zero;

	        {
		        ClosestPointInput input = new ClosestPointInput();

		        GjkPairDetector	gjkPairDetector = new GjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
		        //TODO: if (dispatchInfo.m_useContinuous)
		        gjkPairDetector.SetMinkowskiA(min0);
		        gjkPairDetector.SetMinkowskiB(min1);

		        {
			        input.m_maximumDistanceSquared = min0.Margin + min1.Margin + m_manifoldPtr.GetContactBreakingThreshold();
			        input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
		        }

		        input.m_transformA = body0.GetWorldTransform();
		        input.m_transformB = body1.GetWorldTransform();

		        gjkPairDetector.GetClosestPoints(input,resultOut,dispatchInfo.getDebugDraw(),false);

                if (BulletGlobals.g_streamWriter != null)
                {
                    BulletGlobals.g_streamWriter.WriteLine("c2dc2d processCollision");
                    MathUtil.PrintMatrix(BulletGlobals.g_streamWriter, "transformA", input.m_transformA);
                    MathUtil.PrintMatrix(BulletGlobals.g_streamWriter, "transformB", input.m_transformB);
                }

                //btVector3 v0,v1;
                //btVector3 sepNormalWorldSpace;

	        }

	        if (m_ownManifold)
	        {
		        resultOut.RefreshContactPoints();
	        }

        }
	    public override void ProcessCollision (CollisionObject body0,CollisionObject body1,DispatcherInfo dispatchInfo,ManifoldResult resultOut)
        {
	        if (m_manifoldPtr == null)
            {
		        return;
            }

	        resultOut.SetPersistentManifold(m_manifoldPtr);

	        SphereShape sphere0 = (SphereShape)body0.GetCollisionShape();
	        SphereShape sphere1 = (SphereShape)body1.GetCollisionShape();

	        Vector3 diff = body0.GetWorldTransform().Translation - body1.GetWorldTransform().Translation;
	        float len = diff.Length();
	        float radius0 = sphere0.GetRadius();
	        float radius1 = sphere1.GetRadius();

        #if CLEAR_MANIFOLD
	        m_manifoldPtr.clearManifold(); //don't do this, it disables warmstarting
        #endif

	        ///iff distance positive, don't generate a new contact
	        if ( len > (radius0+radius1))
	        {
        #if !CLEAR_MANIFOLD
		        resultOut.RefreshContactPoints();
        #endif //CLEAR_MANIFOLD
		        return;
	        }
	        ///distance (negative means penetration)
	        float dist = len - (radius0+radius1);

	        Vector3 normalOnSurfaceB = new Vector3(1,0,0);
	        if (len > MathUtil.SIMD_EPSILON)
	        {
		        normalOnSurfaceB = diff / len;
	        }

	        ///point on A (worldspace)
	        ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
	        ///point on B (worldspace)
	        Vector3 pos1 = body1.GetWorldTransform().Translation + radius1* normalOnSurfaceB;

	        /// report a contact. internally this will be kept persistent, and contact reduction is done
        	
	        resultOut.AddContactPoint(ref normalOnSurfaceB,ref pos1,dist);

        #if !CLEAR_MANIFOLD
	        resultOut.RefreshContactPoints();
        #endif //CLEAR_MANIFOLD


        }
	    public override float CalculateTimeOfImpact(CollisionObject body0,CollisionObject body1,DispatcherInfo dispatchInfo,ManifoldResult resultOut)
        {
	        ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold

	        ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
	        ///body0.m_worldTransform,
	        float resultFraction = 1.0f;


	        float squareMot0 = (body0.GetInterpolationWorldTransform().Translation - body0.GetWorldTransform().Translation).LengthSquared();
	        float squareMot1 = (body1.GetInterpolationWorldTransform().Translation - body1.GetWorldTransform().Translation).LengthSquared();

	        if (squareMot0 < body0.GetCcdSquareMotionThreshold() &&
		        squareMot1 < body1.GetCcdSquareMotionThreshold())
            {
		        return resultFraction;
            }

	        //An adhoc way of testing the Continuous Collision Detection algorithms
	        //One object is approximated as a sphere, to simplify things
	        //Starting in penetration should report no time of impact
	        //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
	        //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)


	        /// Convex0 against sphere for Convex1
	        {
		        ConvexShape convex0 = (ConvexShape)(body0.GetCollisionShape());

		        SphereShape	sphere1 = new SphereShape(body1.GetCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
		        CastResult result = new CastResult();
		        VoronoiSimplexSolver voronoiSimplex = new VoronoiSimplexSolver();
		        //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
		        ///Simplification, one object is simplified as a sphere
		        GjkConvexCast ccd1 = new GjkConvexCast( convex0 ,sphere1,voronoiSimplex);
		        //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
		        if (ccd1.CalcTimeOfImpact(body0.GetWorldTransform(),body0.GetInterpolationWorldTransform(),
			        body1.GetWorldTransform(),body1.GetInterpolationWorldTransform(),result))
		        {

			        //store result.m_fraction in both bodies

			        if (body0.GetHitFraction()> result.m_fraction)
                    {
				        body0.SetHitFraction( result.m_fraction );
                    }

			        if (body1.GetHitFraction() > result.m_fraction)
                    {
				        body1.SetHitFraction( result.m_fraction);
                    }

			        if (resultFraction > result.m_fraction)
                    {
				        resultFraction = result.m_fraction;
                    }

		        }
	        }

	        /// Sphere (for convex0) against Convex1
	        {
		        ConvexShape convex1 = (ConvexShape)(body1.GetCollisionShape());

		        SphereShape	sphere0 = new SphereShape(body0.GetCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
		        CastResult result = new CastResult();
		        VoronoiSimplexSolver voronoiSimplex = new VoronoiSimplexSolver();
		        //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
		        ///Simplification, one object is simplified as a sphere
		        GjkConvexCast ccd1 = new GjkConvexCast(sphere0,convex1,voronoiSimplex);
		        //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
		        if (ccd1.CalcTimeOfImpact(body0.GetWorldTransform(),body0.GetInterpolationWorldTransform(),
			        body1.GetWorldTransform(),body1.GetInterpolationWorldTransform(),result))
		        {

			        //store result.m_fraction in both bodies

			        if (body0.GetHitFraction()	> result.m_fraction)
                    {
				        body0.SetHitFraction( result.m_fraction);
                    }

			        if (body1.GetHitFraction() > result.m_fraction)
                    {
				        body1.SetHitFraction( result.m_fraction);
                    }

			        if (resultFraction > result.m_fraction)
                    {
				        resultFraction = result.m_fraction;
                    }

		        }
	        }

	        return resultFraction;
        }
	    public float GetSphereDistance(CollisionObject boxObj,ref Vector3 v3PointOnBox, ref Vector3 v3PointOnSphere, ref Vector3 v3SphereCenter, float fRadius )
        {
	        float margins;
	        Vector3[] bounds = new Vector3[2];
	        BoxShape boxShape= (BoxShape)boxObj.GetCollisionShape();
        	
	        bounds[0] = -boxShape.GetHalfExtentsWithoutMargin();
	        bounds[1] = boxShape.GetHalfExtentsWithoutMargin();

	        margins = boxShape.Margin;//also add sphereShape margin?

	        Matrix m44T = boxObj.GetWorldTransform();

	        Vector3[] boundsVec = new Vector3[2];
	        float	fPenetration;

	        boundsVec[0] = bounds[0];
	        boundsVec[1] = bounds[1];

	        Vector3	marginsVec = new Vector3( margins, margins, margins );

	        // add margins
	        bounds[0] += marginsVec;
	        bounds[1] -= marginsVec;

	        /////////////////////////////////////////////////

	        Vector3	tmp, prel, normal, v3P;
            Vector3[] n = new Vector3[6];

	        float fSep = 10000000.0f;
            float fSepThis;

	        n[0] = new Vector3(-1,0,0);
	        n[1] = new Vector3(0,-1,0);
	        n[2] = new Vector3(0,0,-1);
	        n[3] = new Vector3(1,0,0);
	        n[4] = new Vector3(0,1,0);
	        n[5] = new Vector3(0,0,1);

	        // convert  point in local space
            prel = MathUtil.InverseTransform(ref m44T,ref v3SphereCenter);
        	
	        bool	bFound = false;

	        v3P = prel;

	        for (int i=0;i<6;i++)
	        {
		        int j = i<3? 0:1;
                fSepThis = Vector3.Dot((v3P-bounds[j]),n[i]);
		        if ( fSepThis != 0f)
		        {
			        v3P = v3P - n[i]*fSepThis;		
			        bFound = true;
		        }
	        }
        	
	        //

	        if ( bFound )
	        {
		        bounds[0] = boundsVec[0];
		        bounds[1] = boundsVec[1];

                normal = (prel - v3P);
                normal.Normalize();
		        v3PointOnBox = v3P + normal*margins;
		        v3PointOnSphere = prel - normal*fRadius;

		        if ( (Vector3.Dot((v3PointOnSphere - v3PointOnBox),normal)) > 0f )
		        {
			        return 1f;
		        }

		        // transform back in world space
		        tmp = Vector3.Transform(v3PointOnBox,m44T);
		        v3PointOnBox   = tmp;
		        tmp  = Vector3.Transform(v3PointOnSphere,m44T);		
		        v3PointOnSphere = tmp;
		        float fSeps2 = (v3PointOnBox-v3PointOnSphere).LengthSquared();
        		
		        //if this fails, fallback into deeper penetration case, below
		        if (fSeps2 > MathUtil.SIMD_EPSILON)
		        {
			        fSep = (float)-System.Math.Sqrt(fSeps2);
			        normal = (v3PointOnBox-v3PointOnSphere);
			        normal *= 1f/fSep;
		        }
                    
		        return fSep;
	        }

	        //////////////////////////////////////////////////
	        // Deep penetration case

            fPenetration = GetSpherePenetration(boxObj, ref v3PointOnBox, ref v3PointOnSphere, ref v3SphereCenter, fRadius, ref bounds[0], ref bounds[1]);

	        bounds[0] = boundsVec[0];
	        bounds[1] = boundsVec[1];

	        if ( fPenetration <= 0f)
            {
		        return (fPenetration-margins);
            }
	        else
            {
		        return 1f;
            }
        }
        public override void ProcessCollision(CollisionObject body0,CollisionObject body1,DispatcherInfo dispatchInfo,ManifoldResult resultOut)
        {
	        if (m_manifoldPtr == null)
	        {
		        //swapped?
		        m_manifoldPtr = m_dispatcher.GetNewManifold(body0,body1);
		        m_ownManifold = true;
	        }
            //resultOut = new ManifoldResult();
	        resultOut.SetPersistentManifold(m_manifoldPtr);

	        //comment-out next line to test multi-contact generation
	        //resultOut.getPersistentManifold().clearManifold();
        	

	        ConvexShape min0 = (ConvexShape)(body0.GetCollisionShape());
	        ConvexShape min1 = (ConvexShape)(body1.GetCollisionShape());
        	Vector3  normalOnB = Vector3.Up;
            Vector3  pointOnBWorld = Vector3.Zero;
#if !BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
            if ((min0.ShapeType == BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE) && (min1.ShapeType == BroadphaseNativeTypes.CAPSULE_SHAPE_PROXYTYPE))
	        {
		        CapsuleShape capsuleA = (CapsuleShape) min0;
		        CapsuleShape capsuleB = (CapsuleShape) min1;
		        Vector3 localScalingA = capsuleA.GetLocalScaling();
		        Vector3 localScalingB = capsuleB.GetLocalScaling();
        		
		        float threshold = m_manifoldPtr.GetContactBreakingThreshold();

		        float dist = CapsuleCapsuleDistance(ref normalOnB,ref pointOnBWorld,capsuleA.getHalfHeight(),capsuleA.getRadius(),
			        capsuleB.getHalfHeight(),capsuleB.getRadius(),capsuleA.GetUpAxis(),capsuleB.GetUpAxis(),
			        body0.GetWorldTransform(),body1.GetWorldTransform(),threshold);

		        if (dist<threshold)
		        {
                    Debug.Assert(normalOnB.LengthSquared() >= (MathUtil.SIMD_EPSILON * MathUtil.SIMD_EPSILON));
			        resultOut.AddContactPoint(ref normalOnB,ref pointOnBWorld,dist);	
		        }
		        resultOut.RefreshContactPoints();
		        return;
	        }
#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER



        #if USE_SEPDISTANCE_UTIL2
        	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
            {
                m_sepDistance.updateSeparatingDistance(body0.getWorldTransform(),body1.getWorldTransform());
            }

	        if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
#endif //USE_SEPDISTANCE_UTIL2

    {

        	
	        ClosestPointInput input = new ClosestPointInput();

	        GjkPairDetector	gjkPairDetector = new GjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
	        //TODO: if (dispatchInfo.m_useContinuous)
	        gjkPairDetector.SetMinkowskiA(min0);
	        gjkPairDetector.SetMinkowskiB(min1);

        #if USE_SEPDISTANCE_UTIL2
	        if (dispatchInfo.m_useConvexConservativeDistanceUtil)
	        {
		        input.m_maximumDistanceSquared = float.MaxValue;
	        } 
            else
        #endif //USE_SEPDISTANCE_UTIL2
	        {
		        input.m_maximumDistanceSquared = min0.Margin + min1.Margin + m_manifoldPtr.GetContactBreakingThreshold();
		        input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
	        }

            //input.m_stackAlloc = dispatchInfo.m_stackAllocator;
	        input.m_transformA = body0.GetWorldTransform();
	        input.m_transformB = body1.GetWorldTransform();

	        gjkPairDetector.GetClosestPoints(input,resultOut,dispatchInfo.getDebugDraw(),false);
#if USE_SEPDISTANCE_UTIL2
	float sepDist = 0.f;
	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
	{
		sepDist = gjkPairDetector.getCachedSeparatingDistance();
		if (sepDist>MathUtil.SIMD_EPSILON)
		{
			sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
			//now perturbe directions to get multiple contact points
		}
	}
#endif //USE_SEPDISTANCE_UTIL2

	        //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
        	
	        //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
	        if (m_numPerturbationIterations > 0 &&  resultOut.GetPersistentManifold().GetNumContacts() < m_minimumPointsPerturbationThreshold)
	        {
                Vector3 v0 = Vector3.Zero, v1 = Vector3.Zero;

                Vector3 sepNormalWorldSpace = gjkPairDetector.GetCachedSeparatingAxis();
                sepNormalWorldSpace.Normalize();
                TransformUtil.PlaneSpace1(ref sepNormalWorldSpace, ref v0, ref v1);

		        bool perturbeA = true;
		        const float angleLimit = 0.125f * MathUtil.SIMD_PI;
		        float perturbeAngle;
		        float radiusA = min0.GetAngularMotionDisc();
		        float radiusB = min1.GetAngularMotionDisc();
		        if (radiusA < radiusB)
		        {
			        perturbeAngle = BulletGlobals.gContactBreakingThreshold /radiusA;
			        perturbeA = true;
		        } 
                else
		        {
                    perturbeAngle = BulletGlobals.gContactBreakingThreshold / radiusB;
			        perturbeA = false;
		        }
                if (perturbeAngle > angleLimit)
                {
                    perturbeAngle = angleLimit;
                }

		        Matrix unPerturbedTransform = Matrix.Identity;
		        if (perturbeA)
		        {
			        unPerturbedTransform = input.m_transformA;
		        } 
                else
		        {
			        unPerturbedTransform = input.m_transformB;
		        }
        		
		        for (int i=0;i<m_numPerturbationIterations;i++)
		        {
                    if (v0.LengthSquared() > MathUtil.SIMD_EPSILON)
                    {

                        Quaternion perturbeRot = Quaternion.CreateFromAxisAngle(v0, perturbeAngle);
                        float iterationAngle = i * (MathUtil.SIMD_2_PI / (float)m_numPerturbationIterations);
                        Quaternion rotq = Quaternion.CreateFromAxisAngle(sepNormalWorldSpace, iterationAngle);

                        if (perturbeA)
                        {
                            //input.m_transformA.setBasis(  btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0.getWorldTransform().getBasis());
                            Quaternion temp = MathUtil.QuaternionMultiply(MathUtil.QuaternionInverse(ref rotq),MathUtil.QuaternionMultiply(perturbeRot,rotq));
                            input.m_transformA = MathUtil.BulletMatrixMultiplyBasis(Matrix.CreateFromQuaternion(temp),body0.GetWorldTransform());
                            input.m_transformB = body1.GetWorldTransform();
#if DEBUG_CONTACTS
				        dispatchInfo.m_debugDraw.DrawTransform(ref input.m_transformA,10.0f);
#endif //DEBUG_CONTACTS
                        }
                        else
                        {
                            input.m_transformA = body0.GetWorldTransform();
                            //input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1.getWorldTransform().getBasis());
                            Quaternion temp = MathUtil.QuaternionMultiply(MathUtil.QuaternionInverse(ref rotq),MathUtil.QuaternionMultiply(perturbeRot,rotq));
                            input.m_transformB = MathUtil.BulletMatrixMultiplyBasis(Matrix.CreateFromQuaternion(temp),body1.GetWorldTransform());
#if DEBUG_CONTACTS
				        dispatchInfo.m_debugDraw.DrawTransform(ref input.m_transformB,10.0f);
#endif
                        }

                        PerturbedContactResult perturbedResultOut = new PerturbedContactResult(resultOut, ref input.m_transformA, ref input.m_transformB, ref unPerturbedTransform, perturbeA, dispatchInfo.getDebugDraw());
                        gjkPairDetector.GetClosestPoints(input, perturbedResultOut, dispatchInfo.getDebugDraw(), false);
                    }
        			
        			
		        }
	        }

        	

        #if USE_SEPDISTANCE_UTIL2
	        if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist > MathUtil.SIMD_EPSILON))
	        {
		        m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0.getWorldTransform(),body1.getWorldTransform());
	        }
        #endif //USE_SEPDISTANCE_UTIL2


	        }

	        if (m_ownManifold)
	        {
		        resultOut.RefreshContactPoints();
	        }
        }
Exemple #6
0
        public void	UpdateSingleAabb(CollisionObject colObj)
        {
	        Vector3 minAabb = new Vector3();
            Vector3 maxAabb = new Vector3();
            Matrix wt = colObj.GetWorldTransform();
	        colObj.GetCollisionShape().GetAabb(ref wt, ref minAabb,ref maxAabb);
	        //need to increase the aabb for contact thresholds
            Vector3 contactThreshold = new Vector3(BulletGlobals.gContactBreakingThreshold, BulletGlobals.gContactBreakingThreshold, BulletGlobals.gContactBreakingThreshold);
	        minAabb -= contactThreshold;
	        maxAabb += contactThreshold;



            if (BulletGlobals.g_streamWriter != null && debugCollisionWorld)
            {
                MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "updateSingleAabbMin", minAabb);
                MathUtil.PrintVector3(BulletGlobals.g_streamWriter, "updateSingleAabbMax", maxAabb);
            }


	        IBroadphaseInterface bp = (IBroadphaseInterface)m_broadphasePairCache;

	        //moving objects should be moderately sized, probably something wrong if not
	        if ( colObj.IsStaticObject() || ((maxAabb-minAabb).LengthSquared() < 1e12f))
	        {
		        bp.SetAabb(colObj.GetBroadphaseHandle(),ref minAabb,ref maxAabb, m_dispatcher1);
	        } 
            else
	        {
		        //something went wrong, investigate
		        //this assert is unwanted in 3D modelers (danger of loosing work)
		        colObj.SetActivationState(ActivationState.DISABLE_SIMULATION);

                //static bool reportMe = true;
                bool reportMe = true;
		        if (reportMe && m_debugDrawer != null)
		        {
			        reportMe = false;
			        m_debugDrawer.ReportErrorWarning("Overflow in AABB, object removed from simulation");
			        m_debugDrawer.ReportErrorWarning("If you can reproduce this, please email [email protected]\n");
			        m_debugDrawer.ReportErrorWarning("Please include above information, your Platform, version of OS.\n");
			        m_debugDrawer.ReportErrorWarning("Thanks.\n");
		        }
	        }
        }
Exemple #7
0
    /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
    public static void	ObjectQuerySingle(ConvexShape castShape,ref Matrix convexFromTrans,ref Matrix convexToTrans,
					  CollisionObject collisionObject,CollisionShape collisionShape,
					  ref Matrix colObjWorldTransform,
					  ConvexResultCallback resultCallback, float allowedPenetration)
    {
	    if (collisionShape.IsConvex())
	    {
		    //BT_PROFILE("convexSweepConvex");
		    CastResult castResult = new CastResult();
		    castResult.m_allowedPenetration = allowedPenetration;
		    castResult.m_fraction = resultCallback.m_closestHitFraction;//float(1.);//??

		    ConvexShape convexShape = (ConvexShape) collisionShape;
		    VoronoiSimplexSolver simplexSolver = new VoronoiSimplexSolver();
		    GjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver = new GjkEpaPenetrationDepthSolver();
    		
		    ContinuousConvexCollision convexCaster1 = new ContinuousConvexCollision(castShape,convexShape,simplexSolver, gjkEpaPenetrationSolver);
		    //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
		    //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);

		    IConvexCast castPtr = convexCaster1;
		
		    if (castPtr.CalcTimeOfImpact(ref convexFromTrans,ref convexToTrans,ref colObjWorldTransform,ref colObjWorldTransform,castResult))
		    {
			    //add hit
			    if (castResult.m_normal.LengthSquared() > 0.0001f)
			    {
				    if (castResult.m_fraction < resultCallback.m_closestHitFraction)
				    {
					    castResult.m_normal.Normalize();
					    LocalConvexResult localConvexResult = new LocalConvexResult
								    (
									    collisionObject,
									    null,
									    ref castResult.m_normal,
									    ref castResult.m_hitPoint,
									    castResult.m_fraction
								    );

					    bool normalInWorldSpace = true;
					    resultCallback.AddSingleResult(localConvexResult, normalInWorldSpace);

				    }
			    }
		    }
	    } 
        else 
        {
		    if (collisionShape.IsConcave())
		    {
			    if (collisionShape.ShapeType==BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE)
			    {
				    //BT_PROFILE("convexSweepbtBvhTriangleMesh");
				    BvhTriangleMeshShape triangleMesh = (BvhTriangleMeshShape)collisionShape;
				    Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform);
				    Vector3 convexFromLocal = Vector3.Transform(convexFromTrans.Translation,worldTocollisionObject);
				    Vector3  convexToLocal = Vector3.Transform(convexToTrans.Translation,worldTocollisionObject);
				    // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation

				    Matrix rotationXform = MathUtil.BasisMatrix(ref worldTocollisionObject) *  MathUtil.BasisMatrix(ref convexToTrans);

				    BridgeTriangleConvexcastCallback tccb = new BridgeTriangleConvexcastCallback(castShape, ref convexFromTrans,ref convexToTrans,resultCallback,collisionObject,triangleMesh, ref colObjWorldTransform);
				    tccb.m_hitFraction = resultCallback.m_closestHitFraction;
				    Vector3 boxMinLocal = new Vector3();
                    Vector3 boxMaxLocal = new Vector3();
				    castShape.GetAabb(ref rotationXform, ref boxMinLocal, ref boxMaxLocal);
				    triangleMesh.PerformConvexCast(tccb,ref convexFromLocal,ref convexToLocal,ref boxMinLocal, ref boxMaxLocal);
			    } 
                else
			    {
				    //BT_PROFILE("convexSweepConcave");
				    ConcaveShape concaveShape = (ConcaveShape)collisionShape;
				    Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform);
				    Vector3 convexFromLocal = Vector3.Transform(convexFromTrans.Translation,worldTocollisionObject);
				    Vector3 convexToLocal = Vector3.Transform(convexToTrans.Translation,worldTocollisionObject);
				    // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
                    Matrix rotationXform = MathUtil.BasisMatrix(ref worldTocollisionObject) * MathUtil.BasisMatrix(ref convexToTrans);

                    BridgeTriangleConvexcastCallback2 tccb = new BridgeTriangleConvexcastCallback2(castShape, ref convexFromTrans, ref convexToTrans, resultCallback, collisionObject, concaveShape, ref colObjWorldTransform);
				    tccb.m_hitFraction = resultCallback.m_closestHitFraction;
				    Vector3 boxMinLocal = new Vector3();
                    Vector3 boxMaxLocal = new Vector3();
				    castShape.GetAabb(ref rotationXform, ref boxMinLocal, ref boxMaxLocal);

				    Vector3  rayAabbMinLocal = convexFromLocal;
                    MathUtil.VectorMin(ref convexToLocal,ref rayAabbMinLocal);
                    //rayAabbMinLocal.setMin(convexToLocal);
				    Vector3  rayAabbMaxLocal = convexFromLocal;
                    //rayAabbMaxLocal.setMax(convexToLocal);
                    MathUtil.VectorMax(ref convexToLocal,ref rayAabbMaxLocal);

				    rayAabbMinLocal += boxMinLocal;
				    rayAabbMaxLocal += boxMaxLocal;
				    concaveShape.ProcessAllTriangles(tccb,ref rayAabbMinLocal,ref rayAabbMaxLocal);
			    }
            } 
            else 
            {
			    ///@todo : use AABB tree or other BVH acceleration structure!
			    if (collisionShape.IsCompound())
			    {
                    //BT_PROFILE("convexSweepCompound");
                    CompoundShape compoundShape = (CompoundShape)collisionShape;
				    for (int i=0;i<compoundShape.GetNumChildShapes();i++)
				    {
					    Matrix childTrans = compoundShape.GetChildTransform(i);
					    CollisionShape childCollisionShape = compoundShape.GetChildShape(i);
					    Matrix childWorldTrans = MathUtil.BulletMatrixMultiply(colObjWorldTransform,childTrans);
					    // replace collision shape so that callback can determine the triangle
					    CollisionShape saveCollisionShape = collisionObject.GetCollisionShape();
					    collisionObject.InternalSetTemporaryCollisionShape((CollisionShape)childCollisionShape);

                        LocalInfoAdder my_cb = new LocalInfoAdder(i, resultCallback);
					    my_cb.m_closestHitFraction = resultCallback.m_closestHitFraction;


					    ObjectQuerySingle(castShape, ref convexFromTrans,ref convexToTrans,
						    collisionObject,
						    childCollisionShape,
						    ref childWorldTrans,
						    my_cb, allowedPenetration);
					    // restore
					    collisionObject.InternalSetTemporaryCollisionShape(saveCollisionShape);
				    }
			    }
		    }
	    }
    }
Exemple #8
0
    public virtual void	RayTestSingle(ref Matrix rayFromTrans,ref Matrix rayToTrans,
					  CollisionObject collisionObject,
					  CollisionShape collisionShape,
					  ref Matrix colObjWorldTransform,
					  RayResultCallback resultCallback)
    {
	    SphereShape pointShape = new SphereShape(0.0f);
	    pointShape.Margin = 0f;
	    ConvexShape castShape = pointShape;

	    if (collisionShape.IsConvex())
	    {
    //		BT_PROFILE("rayTestConvex");
		    CastResult castResult = new CastResult();
		    castResult.m_fraction = resultCallback.m_closestHitFraction;

		    ConvexShape convexShape = (ConvexShape)collisionShape;
            VoronoiSimplexSolver simplexSolver = new VoronoiSimplexSolver();
    //#define USE_SUBSIMPLEX_CONVEX_CAST 1
    //#ifdef USE_SUBSIMPLEX_CONVEX_CAST
            
            // FIXME - MAN - convexcat here seems to make big difference to forklift.
            SubSimplexConvexCast convexCaster = new SubSimplexConvexCast(castShape, convexShape, simplexSolver);

            //GjkConvexCast convexCaster = new GjkConvexCast(castShape, convexShape, simplexSolver);


    //#else
		    //btGjkConvexCast	convexCaster(castShape,convexShape,&simplexSolver);
		    //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
    //#endif //#USE_SUBSIMPLEX_CONVEX_CAST

		    if (convexCaster.CalcTimeOfImpact(ref rayFromTrans,ref rayToTrans,ref colObjWorldTransform,ref colObjWorldTransform,castResult))
		    {
			    //add hit
			    if (castResult.m_normal.LengthSquared() > 0.0001f)
			    {
				    if (castResult.m_fraction < resultCallback.m_closestHitFraction)
				    {

                        //if (resultCallback.m_closestHitFraction != 1f)
                        //{
                        //    int ibreak = 0;
                        //    convexCaster.calcTimeOfImpact(ref rayFromTrans, ref rayToTrans, ref colObjWorldTransform, ref colObjWorldTransform, castResult);
                        //}

    //#ifdef USE_SUBSIMPLEX_CONVEX_CAST
					    //rotate normal into worldspace
					    castResult.m_normal = Vector3.TransformNormal(castResult.m_normal,rayFromTrans);
    //#endif //USE_SUBSIMPLEX_CONVEX_CAST

					    castResult.m_normal.Normalize();
					    LocalRayResult localRayResult = new LocalRayResult(
							    collisionObject,
							    null,
							    ref castResult.m_normal,
							    castResult.m_fraction
						    );

					    bool normalInWorldSpace = true;
					    resultCallback.AddSingleResult(localRayResult, normalInWorldSpace);

				    }
			    }
		    }
            castResult.Cleanup();
	    } 
        else 
        {
		    if (collisionShape.IsConcave())
		    {
    //			BT_PROFILE("rayTestConcave");
		    	if (collisionShape.ShapeType==BroadphaseNativeTypes.TRIANGLE_MESH_SHAPE_PROXYTYPE && collisionShape is BvhTriangleMeshShape)
	    		{
				    ///optimized version for btBvhTriangleMeshShape
					BvhTriangleMeshShape triangleMesh = (BvhTriangleMeshShape)collisionShape;
				    Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform);
				    Vector3 rayFromLocal = Vector3.Transform(rayFromTrans.Translation,worldTocollisionObject);
				    Vector3 rayToLocal = Vector3.Transform(rayToTrans.Translation,worldTocollisionObject);

                    Matrix transform = Matrix.Identity;
				    BridgeTriangleRaycastCallback rcb = new BridgeTriangleRaycastCallback(ref rayFromLocal,ref rayToLocal, resultCallback,collisionObject,triangleMesh,ref transform);
				    rcb.m_hitFraction = resultCallback.m_closestHitFraction;
				    triangleMesh.PerformRaycast(rcb,ref rayFromLocal,ref rayToLocal);
                    rcb.Cleanup();
			    } 
                else
			    {
				    //generic (slower) case
				    ConcaveShape concaveShape = (ConcaveShape)collisionShape;

				    Matrix worldTocollisionObject = Matrix.Invert(colObjWorldTransform);

				    Vector3 rayFromLocal = Vector3.Transform(rayFromTrans.Translation,worldTocollisionObject);
				    Vector3 rayToLocal = Vector3.Transform(rayToTrans.Translation,worldTocollisionObject);

				    //ConvexCast::CastResult
                    Matrix transform = Matrix.Identity;
                    BridgeTriangleConcaveRaycastCallback rcb = new BridgeTriangleConcaveRaycastCallback(ref rayFromLocal, ref rayToLocal, resultCallback, collisionObject, concaveShape,ref transform);
				    rcb.m_hitFraction = resultCallback.m_closestHitFraction;

				    Vector3 rayAabbMinLocal = rayFromLocal;
				    MathUtil.VectorMin(ref rayToLocal,ref rayAabbMinLocal);
				    Vector3 rayAabbMaxLocal = rayFromLocal;
                    MathUtil.VectorMax(ref rayToLocal,ref rayAabbMaxLocal);

				    concaveShape.ProcessAllTriangles(rcb,ref rayAabbMinLocal,ref rayAabbMaxLocal);
                    rcb.Cleanup();
			    }
		    } 
            else 
            {
                // BT_PROFILE("rayTestCompound");
			    ///@todo: use AABB tree or other BVH acceleration structure, see btDbvt
			    if (collisionShape.IsCompound())
			    {
				    CompoundShape compoundShape = (CompoundShape)(collisionShape);
				    int i=0;
				    for (i=0;i<compoundShape.GetNumChildShapes();i++)
				    {
					    Matrix childTrans = compoundShape.GetChildTransform(i);
					    CollisionShape childCollisionShape = compoundShape.GetChildShape(i);
					    Matrix childWorldTrans = MathUtil.BulletMatrixMultiply(colObjWorldTransform,childTrans) ;
					    // replace collision shape so that callback can determine the triangle
					    CollisionShape saveCollisionShape = collisionObject.GetCollisionShape();
					    collisionObject.InternalSetTemporaryCollisionShape((CollisionShape)childCollisionShape);

                        LocalInfoAdder2 my_cb = new LocalInfoAdder2(i, resultCallback);
					    my_cb.m_closestHitFraction = resultCallback.m_closestHitFraction;
					
					    RayTestSingle(ref rayFromTrans,ref rayToTrans,
						    collisionObject,
						    childCollisionShape,
						    ref childWorldTrans,
						    my_cb);
					    // restore
					    collisionObject.InternalSetTemporaryCollisionShape(saveCollisionShape);
                        my_cb.cleanup();
				    }
			    }
		    }
	    }
    }
Exemple #9
0
        public virtual void AddCollisionObject(CollisionObject collisionObject, CollisionFilterGroups collisionFilterGroup, CollisionFilterGroups collisionFilterMask)
        {
    	    //check that the object isn't already added
            //btAssert( m_collisionObjects.findLinearSearch(collisionObject)  == m_collisionObjects.size());

            Debug.Assert(collisionObject != null);
		    m_collisionObjects.Add(collisionObject);

		    //calculate new AABB
		    Matrix trans = collisionObject.GetWorldTransform();
            Vector3 minAabb = new Vector3();
            Vector3 maxAabb= new Vector3();

		    collisionObject.GetCollisionShape().GetAabb(ref trans,ref minAabb,ref maxAabb);

		    BroadphaseNativeTypes type = collisionObject.GetCollisionShape().ShapeType;
		    collisionObject.SetBroadphaseHandle( GetBroadphase().CreateProxy(
			    ref minAabb,
			    ref maxAabb,
			    type,
			    collisionObject,
			    collisionFilterGroup,
			    collisionFilterMask,
			    m_dispatcher1,0
			    ))	;
        }