Cylinder Orientation between two points on a sphere, Scenekit, Quaternions IOS

后端 未结 6 880
南笙
南笙 2020-12-17 00:04

I\'ve been trying to draw a cylinder between two points on the outer edge of a sphere using SceneKit. I have already produced a line between these two points using primitive

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-17 00:21

    Just for reference a more elegant SCNCyclinder implementation to connect a start and end position with a given radius:

    func makeCylinder(from: SCNVector3, to: SCNVector3, radius: CGFloat) -> SCNNode
    {
        let lookAt = to - from
        let height = lookAt.length()
    
        let y = lookAt.normalized()
        let up = lookAt.cross(vector: to).normalized()
        let x = y.cross(vector: up).normalized()
        let z = x.cross(vector: y).normalized()
        let transform = SCNMatrix4(x: x, y: y, z: z, w: from)
    
        let geometry = SCNCylinder(radius: radius, 
                                   height: CGFloat(height))
        let childNode = SCNNode(geometry: geometry)
        childNode.transform = SCNMatrix4MakeTranslation(0.0, height / 2.0, 0.0) * 
          transform
    
        return childNode
    }
    

    Needs the following extension:

    extension SCNVector3 {
        /**
         * Calculates the cross product between two SCNVector3.
         */
        func cross(vector: SCNVector3) -> SCNVector3 {
            return SCNVector3Make(y * vector.z - z * vector.y, z * vector.x - x * vector.z, x * vector.y - y * vector.x)
        }
    
        func length() -> Float {
            return sqrtf(x*x + y*y + z*z)
        }
    
        /**
         * Normalizes the vector described by the SCNVector3 to length 1.0 and returns
         * the result as a new SCNVector3.
         */
        func normalized() -> SCNVector3 {
            return self / length()
        }
    }
    
    extension SCNMatrix4 {
        public init(x: SCNVector3, y: SCNVector3, z: SCNVector3, w: SCNVector3) {
            self.init(
                m11: x.x,
                m12: x.y,
                m13: x.z,
                m14: 0.0,
    
                m21: y.x,
                m22: y.y,
                m23: y.z,
                m24: 0.0,
    
                m31: z.x,
                m32: z.y,
                m33: z.z,
                m34: 0.0,
    
                m41: w.x,
                m42: w.y,
                m43: w.z,
                m44: 1.0)
        }
    }
    
    /**
     * Divides the x, y and z fields of a SCNVector3 by the same scalar value and
     * returns the result as a new SCNVector3.
     */
    func / (vector: SCNVector3, scalar: Float) -> SCNVector3 {
        return SCNVector3Make(vector.x / scalar, vector.y / scalar, vector.z / scalar)
    }
    
    func * (left: SCNMatrix4, right: SCNMatrix4) -> SCNMatrix4 {
        return SCNMatrix4Mult(left, right)
    }
    

提交回复
热议问题