开发者

Friction in physics engine help

Ok i know this is sort of a non specific question but i am making a verlet integration physics engine for a game similar to, for example angry birds. I am writing a practice engine just to get the jist of it (credits for simpler c++ version go to Benedikt Bitterli) and no matter what i do i cant figure out how to implement friction. I posted the main collision and caluculation methods below if someone could at least tell me where or in which method i should add something and the name of the techneque or somthing.

private void updateVerlet() {
    float tempX;
    float tempY;

    for (int b = 0; b < bodies.size(); b++) {
        for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
            Vertex v = bodies.get(b).vertices.get(i);
            tempX = v.x;
            tempY = v.y;
            v.x += v.x - v.ox + v.accx * timestep * timestep;
            v.y += v.y - v.oy + v.accy * timestep * timestep;
            v.ox = tempX;
            v.oy = tempY;
        }
    }
}



private void updateEdges() {
    for (int b = 0; b < bodies.size(); b++) {
        for (int i = 0; i < bodies.get(b).edges.size(); i++) {
            Edge e = bodies.get(b).edges.get(i);

            float distX = e.v2.x - e.v1.x;
            float distY = e.v2.y - e.v1.y;

            float dist = (float)Math.hypot(distX, distY);
            float diff = dist - e.length;

            float len = 1f / (float)Math.hypot(distX, distY);// Normalize with (float)Math.hypot(distX, distY); again????
            distX *= len;
            distY *= len;

            e.v1.x += distX * diff * 0.5;
            e.v1.y += distY * diff * 0.5;
            e.v2.x -= distX * diff * 0.5;
            e.v2.y -= distY * diff * 0.5;
        }
    }
}
private void iterateCollisions() {
    for (int iteration = 0; iteration < iterations; iteration++) {

        // Temporary solution to prevent bodies from falling out of the screen
        for (int b = 0; b < bodies.size(); b++) {
            for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
                bodies.get(b).vertices.get(i).x = Math.max(Math.min(bodies.get(b).vertices.get(i).x, (float)screenWidth), 0.0f);
                bodies.get(b).vertices.get(i).y = Math.max(Math.min(bodies.get(b).vertices.get(i).y, (float)screenHeight), 0.0f);
            }
        }

        updateEdges();

        for (int b = 0; b < bodies.size(); b++) {
            bodies.get(b).calculateCenter();
        }

        for (int b1 = 0; b1 < bodies.size(); b1++) {
            for (int b2 = 0; b2 < bodies.size(); b2++) {
                if (bodies.get(b1) != bodies.get(b2)) {
                    if (bodiesOverlap(bodies.get(b1), bodies.get(b2))) {
                        if (detectCollision(bodies.get(b1), bodies.get(b2))) {
                            processCollision();
                        }
                    }
                }
            }
        }

    }
}
private boolean bodiesOverlap(PhysicsBody b1, PhysicsBody b2) {
    return
    (b1.minX <= b2.maxX) &a开发者_JS百科mp;&
    (b1.minY <= b2.maxY) &&
    (b1.maxX >= b2.minX) &&
    (b2.maxY >= b1.minY);
}

private boolean detectCollision(PhysicsBody b1, PhysicsBody b2) {
    float minDistance = 10000.0f;
    Edge e;

    for (int i = 0; i < b1.edges.size() + b2.edges.size(); i++) {
        if (i < b1.edges.size()) {
            e = b1.edges.get(i);
        } else {
            e= b2.edges.get(i - b1.edges.size());
        }

        if (!e.boundary)
            continue;

        axis.x = e.v1.y - e.v2.y;
        axis.y = e.v2.x - e.v1.x;

        float len = 1f / (float)Math.hypot(axis.x, axis.y);
        axis.x *= len;
        axis.y *= len;

        MinMax dataA = b1.projectToAxis(axis);
        MinMax dataB = b2.projectToAxis(axis);

        float distance = intervalDistance(dataA, dataB);

        if (distance > 0f)
            return false;
        else if (Math.abs(distance) < minDistance) {
            minDistance = Math.abs(distance);

            CollisionInfo.normalX = axis.x;
            CollisionInfo.normalY = axis.y;
            CollisionInfo.e = e;
        }
    }

    CollisionInfo.depth = minDistance;

    if (CollisionInfo.e.parent != b2) {
        PhysicsBody temp = b2;
        b2 = b1;
        b1 = temp;
    }

    float diffX = b1.centerX - b2.centerX;
    float diffY = b1.centerY - b2.centerY;
    float mult = CollisionInfo.normalX * diffX + CollisionInfo.normalY * diffY;

    if (mult < 0) {
        CollisionInfo.normalX = 0 - CollisionInfo.normalX;
        CollisionInfo.normalY = 0 - CollisionInfo.normalY;
    }

    minDistance = 10000.0f;

    for (int i = 0; i < b1.vertices.size(); i++) {
        diffX = b1.vertices.get(i).x - b2.centerX;
        diffY = b1.vertices.get(i).y - b2.centerY;
        float distance = CollisionInfo.normalX * diffX + CollisionInfo.normalX * diffY;

        if (distance < minDistance) {
            minDistance = distance;
            CollisionInfo.v = b1.vertices.get(i);
        }
    }
    return true;
}

private void processCollision() {
    Vertex v1 = CollisionInfo.e.v1;
    Vertex v2 = CollisionInfo.e.v2;

    float collisionVectorX = CollisionInfo.normalX * CollisionInfo.depth;
    float collisionVectorY = CollisionInfo.normalY * CollisionInfo.depth;

    float t;
    if (Math.abs(v1.x - v2.x) > Math.abs(v1.y - v2.y)) {
        t = (CollisionInfo.v.x - collisionVectorX - v1.x) / (v2.x - v1.x);
    }
    else {
        t = (CollisionInfo.v.y - collisionVectorY - v1.y) / (v2.y - v1.y);
    }

    float lambda = 1.0f / (t * t + (1 - t) * (1 - t));
    float edgeMass = t * v2.parent.mass + (1f - t) * v1.parent.mass;
    float invCollisionMass = 1.0f / (edgeMass + CollisionInfo.v.parent.mass);

    float ratio1 = CollisionInfo.v.parent.mass * invCollisionMass;
    float ratio2 = edgeMass*invCollisionMass;

    v1.x -= collisionVectorX * ((1 - t) * ratio1 * lambda);
    v1.y -= collisionVectorY * (( 1 - t) * ratio1 * lambda);
    v2.x -= collisionVectorX * (t * ratio1 * lambda);
    v2.y -= collisionVectorY * (t * ratio1 * lambda);

    CollisionInfo.v.x += collisionVectorX * ratio2;
    CollisionInfo.v.y += collisionVectorY * ratio2;
}


try this code, friction on the bottom world boundary for every particle, limit horizontal movement.

if(Particle.Y >= world_height) { Particle.OldX = Particle.OldX - (Particle.OldX - Particle.X)/2; }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜