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
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)
}