如何根据枢轴调整节点

How to adjust node as per pivot

场景包中

假设 我有 2 个 BOX,带 PIVOT 的 box1,不带 PIVOT

的 box2

我的目标是通过转换匹配两个框

      let plane = SCNBox(width: 12, height: 2, length: 12, chamferRadius: 0)
      plane.firstMaterial?.diffuse.contents = UIColor.red
      let planeNode = SCNNode(geometry: plane)
      planeNode.name = "Plane1"
      planeNode.pivot  = SCNMatrix4MakeTranslation(0, -0.5, 0)

方框 2

      let plane2 = SCNBox(width: 12, height: 2, length: 12, chamferRadius: 0)
      plane2.firstMaterial?.diffuse.contents = UIColor.red
      let planeNode2 = SCNNode(geometry: plane2)
      planeNode2.name = "Plane2"

现在我缩放 BOX1 和 box2

planeNode.scale.y = 4 planeNode2.scale.y = 4

因为 planeNode 有枢轴所以它将从底部开始缩放,但是 Plane2 将从中心开始缩放

我如何计算 plane2 的位置以匹配 plane1

你的两个盒子都有支点。默认情况下,对于 SCNBox,它位于对象中心(边界框的中心)。您所做的是移动第一个 Box 的 Pivot。场景对象将始终相对于其当前枢轴位置放置。所以当你向上移动Y轴的枢轴时,物体将处于较低的位置。

当您将第二个对象设置为与第一个对象相同的位置时,您可以匹配两个对象的位置,然后将第一个对象的枢轴的反向偏移添加到第二个对象的位置。

制作这样的东西:

func alignPosition() {
    
    // Calculate offset position
    let offset = SCNVector3(planeNode.pivot.m41, planeNode.pivot.m42, planeNode.pivot.m43)
    
    // Set the seconds node to the position as the first node
    // without changing it's pivot, then subtract the offset
    planeNode2.position = planeNode.position - offset
    
}

您还需要这个数学扩展:

extension CGPoint {
    
    init(_ size: CGSize) {
        self.init()
        self.x = size.width
        self.y = size.height
    }
    
    init(_ vector: SCNVector3) {
        self.init()
        self.x = CGFloat(vector.x)
        self.y = CGFloat(vector.y)
    }
    
    func distanceTo(_ point: CGPoint) -> CGFloat {
        return (self - point).length()
    }
    
    func length() -> CGFloat {
        return sqrt(self.x * self.x + self.y * self.y)
    }
    
    func midpoint(_ point: CGPoint) -> CGPoint {
        return (self + point) / 2
    }
    static func + (left: CGPoint, right: CGPoint) -> CGPoint {
        return CGPoint(x: left.x + right.x, y: left.y + right.y)
    }
    
    static func - (left: CGPoint, right: CGPoint) -> CGPoint {
        return CGPoint(x: left.x - right.x, y: left.y - right.y)
    }
    
    static func += (left: inout CGPoint, right: CGPoint) {
        left = left + right
    }
    
    static func -= (left: inout CGPoint, right: CGPoint) {
        left = left - right
    }
    
    static func / (left: CGPoint, right: CGFloat) -> CGPoint {
        return CGPoint(x: left.x / right, y: left.y / right)
    }
    
    static func * (left: CGPoint, right: CGFloat) -> CGPoint {
        return CGPoint(x: left.x * right, y: left.y * right)
    }
    
    static func /= (left: inout CGPoint, right: CGFloat) {
        left = left / right
    }
    
    static func *= (left: inout CGPoint, right: CGFloat) {
        left = left * right
    }
}

extension SCNVector3
{
    static func + (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
        return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
    }
    
    static func - (left: SCNVector3, right: SCNVector3) -> SCNVector3 {
        return SCNVector3Make(left.x - right.x, left.y - right.y, left.z - right.z)
    }
    
    static func * (vector: SCNVector3, scalar: Float) -> SCNVector3 {
        return SCNVector3Make(vector.x * scalar, vector.y * scalar, vector.z * scalar)
    }
    
    static func / (vector: SCNVector3, scalar: Float) -> SCNVector3 {
        if scalar == 0.0 { return SCNVector3() }
        return SCNVector3Make(vector.x / scalar, vector.y / scalar, vector.z / scalar)
    }
    
    func lengthSquared() -> Float {
        return x*x + y*y + z*z
    }

    func length() -> Float {
        return sqrtf(lengthSquared())
    }

    func normalize() -> SCNVector3 {
        let len:Float = 1.0 / sqrt(lengthSquared())
        return self * len
    }
    
    func distanceFrom(_ v: SCNVector3) -> Float {
        let dx = x - v.x
        let dy = y - v.y
        let dz = z - v.z
        return sqrt(dx*dx + dy*dy + dz*dz)
    }
    
    func minus(_ other:SCNVector3) -> SCNVector3 { return SCNVector3(x - other.x, y - other.y, z - other.z) }
    
    func normalized() -> SCNVector3 {
        let len = length()
        var ans = SCNVector3()
        ans.x = self.x / len
        ans.y = self.y / len
        ans.z = self.z / len
        return ans
    }
}