Esempio n. 1
0
    /// <summary>
    /// This function fixed contacts only with external objects for capsule
    /// </summary>
    private void FixContact(ref ShapeContact contact)
    {
        Vec3 firstPoint = Vec3.ZERO;

        // set first point for intersection
        // it's bottom or top sphere of capsule
        // or cylinder part of capsule
        if (contact.Point.z < shape.BottomCap.z)
        {
            firstPoint = shape.BottomCap;
        }
        else if (shape.BottomCap.z <= contact.Point.z && contact.Point.z <= shape.TopCap.z)
        {
            firstPoint = new Vec3(shape.TopCap.x, shape.TopCap.y, contact.Point.z);
        }
        else
        {
            firstPoint = shape.TopCap;
        }

        // try get contact object
        WorldIntersectionNormal normalIntersection = new WorldIntersectionNormal();
        var hitObj = World.GetIntersection(firstPoint, contact.Point, contactsIntersectionMask, normalIntersection);

        if (hitObj)
        {
            // get real distance to contact
            float distance = (float)(normalIntersection.Point - firstPoint).Length;
            if (distance < shape.Radius)
            {
                // set correct parameters for contact
                contact.Point  = normalIntersection.Point;
                contact.Depth  = shape.Radius - distance;
                contact.Normal = new vec3((firstPoint - contact.Point).Normalize());
            }
            else
            {
                // contact outside capsule
                contact.Point  = Vec3.ZERO;
                contact.Depth  = 0.0f;
                contact.Normal = vec3.ZERO;
            }
        }
        // check contact with horizontal plane, because intersection can't detect it
        else if (MathLib.Dot(vec3.UP, contact.Normal) < MathLib.EPSILON)
        {
            if (contact.Object)
            {
                vec3 scale = contact.Object.WorldScale;

                // check object scale
                if (MathLib.Compare(scale.x, 1.0f) != 1 ||
                    MathLib.Compare(scale.y, 1.0f) != 1 ||
                    MathLib.Compare(scale.z, 1.0f) != 1)
                {
                    // this value avoids jittering
                    contact.Depth = MathLib.Max(Physics.PenetrationTolerance, 0.01f);
                }
            }
        }
        else
        {
            // capsule does not contact with this object
            contact.Point  = Vec3.ZERO;
            contact.Depth  = 0.0f;
            contact.Normal = vec3.ZERO;
        }
    }
Esempio n. 2
0
    private void TryMoveDown(float ifps)
    {
        vec3 moveImpulseXY = moveImpulse - vec3.UP * MathLib.Dot(vec3.UP, moveImpulse);
        Vec3 pos1          = position + (moveImpulseXY.Normalized + vec3.UP) * shape.Radius;
        Vec3 pos2          = pos1 - vec3.UP * shape.Radius;

        WorldIntersectionNormal intersection = new WorldIntersectionNormal();

        Unigine.Object hitObj = World.GetIntersection(pos1, pos2, contactsIntersectionMask, intersection);
        if (hitObj)
        {
            float angle = MathLib.GetAngle(vec3.UP, intersection.Normal);
            if (autoSteppingCancelAngle < angle && angle < 90.0f)
            {
                position        -= autoSteppingOffset;
                usedAutoStepping = false;
                return;
            }
        }

        vec3 velocityXY = velocity - vec3.UP * MathLib.Dot(vec3.UP, velocity);

        pos1   = position + (velocityXY.Normalized + vec3.UP) * shape.Radius;
        pos2   = pos1 - vec3.UP * shape.Radius;
        hitObj = World.GetIntersection(pos1, pos2, contactsIntersectionMask, intersection);
        if (hitObj)
        {
            float angle = MathLib.GetAngle(vec3.UP, intersection.Normal);
            if (autoSteppingCancelAngle < angle && angle < 90.0f)
            {
                position        -= autoSteppingOffset;
                usedAutoStepping = false;
                return;
            }
        }

        // this correction allows to avoid jittering on large stairs
        if (lastStepHeight > shape.Radius)
        {
            if (GravityMultiplier > 1.0f)
            {
                lastStepHeight = shape.Radius / GravityMultiplier - Physics.PenetrationTolerance;
            }
            else
            {
                lastStepHeight = shape.Radius - Physics.PenetrationTolerance;
            }
        }

        // try to drop down the player
        position           -= new vec3(zAxis * lastStepHeight);
        autoSteppingOffset -= new vec3(zAxis * lastStepHeight);

        // move (apply "position")
        dummy.Transform = GetBodyTransform();

        // find collisions with the capsule
        shape.GetCollision(contacts, 0.0f);
        if (contacts.Count == 0)
        {
            return;
        }

        int contactsCount = MathLib.Min(contacts.Count, contactsBufferSize);

        float inumContacts = 1.0f / MathLib.Itof(contactsCount);

        // push up (if collisions exists)
        for (int i = 0; i < contactsCount; i++)
        {
            ShapeContact c = contacts[i];

            position += new vec3(zAxis * (MathLib.Max(c.Depth, 0.0f) * inumContacts * MathLib.Dot(zAxis, c.Normal)));

            if (MathLib.Dot(c.Normal, vec3.UP) > 0.5f && MathLib.Dot(new vec3(c.Point - shape.BottomCap), vec3.UP) < 0.0f)
            {
                IsGround = true;
            }
        }

        if (renderDownPassContacts)
        {
            foreach (var c in contacts)
            {
                Visualizer.RenderVector(c.Point, c.Point + c.Normal, new vec4(0, 1, 0, 1));
            }
        }
    }