示例#1
0
 distToSegment: function(p, v1, v2) {
     var v = new Point(v2.x,v2.y);
     v.subtract(v1);
     var w = new Point(p.x,p.y);
     w.subtract(v1);
     var c1 = w.dot(v);
     var c2 = v.dot(v);
     if (!c2) return 100000;
     var b = c1/c2;
     v.multiply(b);
     var Pb = new Point(v1.x, v1.y);
     Pb.add(v);
     return Point.distance(p, Pb);
 },
示例#2
0
    applyFriction: function(collisionInfo) {

        var edgePoint1 = collisionInfo.edge[0],
            edgePoint2 = collisionInfo.edge[1],
            tangentDirection = Point.subtract(edgePoint2.position, edgePoint1.position).normalize(),
            pointSpeed = collisionInfo.point.getSpeed(),
            edgeSpeed = edgePoint1.getSpeed().add(edgePoint2.getSpeed()).multiply(0.5);

        if (!collisionInfo.depth) {
            return;
        }

        var frictionRatio =  Math.max(Math.min(collisionInfo.depth / this.FRICTION_RATIO, 1), this.FRICTION_MIN), // Bigger ratio - more friction

            tangentPointSpeed = tangentDirection.dot(pointSpeed),
            tangentEdgeSpeed = tangentDirection.dot(edgeSpeed),
            speedDelta = tangentPointSpeed - tangentEdgeSpeed,
            deltaToApply = speedDelta * frictionRatio,
            invMassEdge = 0;

        if (edgePoint1.mass * edgePoint2.mass > 0) {
            invMassEdge = 1 / (edgePoint1.mass + edgePoint2.mass);
        }

        deltaToApply /= (collisionInfo.point.invMass + invMassEdge);

        collisionInfo.point.applyForce(Point.multiply(tangentDirection, -deltaToApply * collisionInfo.point.invMass));
        edgePoint1.applyForce(Point.multiply(tangentDirection, deltaToApply * edgePoint1.invMass));
        edgePoint2.applyForce(Point.multiply(tangentDirection, deltaToApply * edgePoint2.invMass));
    },
示例#3
0
    moveParticles: function(dt) {

        for (var i = 0; i < this.particles.length; i++) {
            var particle = this.particles[i];
            if (particle.enabled && particle.mass > 0) {
                var delta = Point.subtract(particle.position, particle.prevPosition);
                particle.prevPosition = particle.position.clone();
                particle.position.addPoint(delta);
                particle.position.addPoint(Point.multiplyFloat(particle.acceleration, dt * dt));
            }
        }
    },
示例#4
0
    processConstraints: function(list) {

        if (!list) {
            list = this.constraints;
        }

        for (var i = 0; i < list.length; i++) {
            var constraint = list[i];
            if (constraint.enabled) {
                var point1 = constraint.particle1.position;
                var point2 = constraint.particle2.position;

                // delta = x2 - x1

                var delta = Point.subtract(point2, point1),
                    deltaLength = delta.getMagnitude();

                if (Math.abs(deltaLength) < 0.0000001) { // Ignore same place points to avoid division by zero
                    return;
                }

                var diff = (deltaLength - constraint.length) / (deltaLength * (constraint.particle1.invMass + constraint.particle2.invMass)),
                    shouldProcess = false;

                if (constraint.type == Constraint.TYPE_EQUAL) {
                    shouldProcess = Math.abs(diff) > 0;
                } else if (constraint.type == Constraint.TYPE_GREATER) {
                    shouldProcess = diff < 0;
                } else if (constraint.type == Constraint.TYPE_LESS) {
                    shouldProcess = diff > 0;
                }

                if (shouldProcess) {
                    delta.multiply(diff * constraint.stiffness);
                    point1.add(Point.multiply(delta, constraint.particle1.invMass));
                    point2.subtract(Point.multiply(delta, constraint.particle2.invMass));
                }
            }
        }
    },
示例#5
0
    collideConvexes: function(convex1, convex2, collisionInfo, isSecond) {

        if (collisionInfo.depth === undefined) {
            collisionInfo.depth = 1000000; // Large value
        }

        collisionInfo.convex1 = convex1;
        collisionInfo.convex2 = convex2;

        var minDepth = collisionInfo.depth,
            collisionNormal = null,
            collisionEdge = null,
            foundBestNormal = false,
            interval = null;

        // Getting collision normal and depth
        for (var i = 0; i < convex1.particles.length; i++) {
            var particle1 = convex1.particles[i],
                particle2 = convex1.particles[(i + 1) % convex1.particles.length],
                p1 = particle1.position,
                p2 = particle2.position,
                normal = new Point(p1.y - p2.y, p2.x - p1.x).normalize();

            var projection1 = this.projectConvexToAxis(convex1, normal),
                projection2 = this.projectConvexToAxis(convex2, normal);
                interval = this.intervalDistance(projection1, projection2);

            var distance = interval.distance,
                centersDirection = Point.subtract(convex1.center, convex2.center),

                // Projection must be positive (normal looks in the correct direction)
                // if not - it's probably a parallel edge which must be ignored
                normalResponseProjection = centersDirection.dot(normal);

            if (distance > 0) {
                return false;
            } else if (normalResponseProjection > 0 && Math.abs(distance) < minDepth) {
                minDepth = Math.abs(distance);
                collisionNormal = normal;
                foundBestNormal = true;
                collisionEdge = [particle1, particle2];
            }
        }

        if (foundBestNormal) {

            var maxDistance = 0,
                firstPointOnCorrectSide = null;

            for (i = 0; i < convex2.particles.length; i++) {
                if (Point.ord(convex2.particles[i].position, collisionEdge[0].position, collisionEdge[1].position) > 0) {
                    var pointToLineDistance = this.distToSegment(convex2.particles[i].position, collisionEdge[0].position, collisionEdge[1].position);
                    if (Math.abs(pointToLineDistance) > maxDistance) {
                        maxDistance  = Math.abs(pointToLineDistance);
                        collisionInfo.point = convex2.particles[i];
                    }

                    firstPointOnCorrectSide = convex2.particles[i];
                }
            }

            if (!collisionInfo.point) {
                collisionInfo.point = firstPointOnCorrectSide || convex2.particles[0];
            }

            collisionInfo.axis = collisionNormal;
            collisionInfo.edge = collisionEdge;
            collisionInfo.depth = minDepth;
        }

        return true;
    },