Swift Rope Verlets

时间:2014-12-15 07:50:34

标签: swift verlet-integration

我试图在swift中实现一个verlet绳索。我遇到了这样的问题:当试图从约束中修复点质量的位置时,它们会迅速分开,然后坐标变为NaN。知道我的代码中可能有什么问题吗?

import Foundation

private let DEF_POINT_COUNT = 10
private let CONST_ITERATIONS = 5

@objc class PointMass: DebugPrintable {
    var point: NSPoint
    private var oldPoint: NSPoint

    var x: Double {
        get { return Double(point.x) }
    }

    var y: Double {
        get { return Double(point.y) }
    }

    var debugDescription: String {
        get { return "\(point)" }
    }

    init(_ point: NSPoint) {
        self.point = point
        self.oldPoint = point
    }

    func updatePosition() {
        let dx = point.x - oldPoint.x
        let dy = (point.y - oldPoint.y)

        oldPoint = point

        point = NSPoint(x: point.x + dx, y: point.y + dy)
    }

    func updatePosition(point: NSPoint) {
        let dx = point.x - self.point.x
        let dy = point.y - self.point.y
        self.oldPoint = NSPoint(x: oldPoint.x + dx, y: oldPoint.y + dy)
        self.point = point
    }
}

struct Constraint {
    var p1: PointMass
    var p2: PointMass
    var len: Double

    func fixPoints() {
        let dx = p2.x - p1.x
        let dy = p2.y - p1.y

        let dist = sqrt(dx*dx + dy*dy)

        let diff = (dist - len)/len

        p2.updatePosition(NSPoint(x: p2.x - diff*dx*0.5, y: p2.y - diff*dy*0.5))
        p1.updatePosition(NSPoint(x: p1.x + diff*dx*0.5, y: p1.y + diff*dy*0.5))
    }
}

@objc class Rope: NSObject {
    let points: [PointMass]
    let constraints: [Constraint]

    init(anchor: NSPoint, end: NSPoint, length: Double, count: Int = DEF_POINT_COUNT) {
        let anchorPoint = PointMass(anchor)
        let endPoint = PointMass(end)

        let dx = (anchorPoint.x - endPoint.x)/Double(count)
        let dy = (anchorPoint.y - endPoint.y)/Double(count)

        let constraintLength = length/Double(count)

        var points = [endPoint]
        var constraints: [Constraint] = []

        for i in 1...count {
            let prevPoint = points[i-1]
            let newPoint = PointMass(NSPoint(x: prevPoint.x + dx, y: prevPoint.y + dy))

            let constraint = Constraint(p1: prevPoint, p2: newPoint, len: constraintLength)

            points.append(newPoint)
            constraints.append(constraint)
        }

        self.points = points
        self.constraints = constraints
    }

    func update(anchor: NSPoint, endPoint: NSPoint) {
        points.first?.updatePosition(endPoint)
        points.last?.updatePosition(anchor)

        for point in points {
            point.updatePosition()
        }

        for i in 0...CONST_ITERATIONS {
            for constraint in constraints {
                constraint.fixPoints()
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

找到它。问题在于fixPoints()方法,正如我所怀疑的那样。

该行

let diff = (dist - len)/len

应该是

let diff = (len - dist)/dist