I am trying to replicate this cube image shape (with permission from the original creator) using scene kit.
Thus far, I have the drawing code for the lines and the vertices. I cannot use an image because the background has to be transparent.
The specific I am trying to solve right now is how to edit the stroke width for the SCNGeometryPrimitiveType.Line
element.
The basic way I am creating lines is like this:
private func squareVertices(length: Float) -> [SCNVector3] {
let m = length/Float(2)
let topLeft = SCNVector3Make(-m-q, m+q, m+q)
let topRight = SCNVector3Make( m+q, m+q, m+q)
let bottomLeft = SCNVector3Make(-m-q, -m-q, m+q)
let bottomRight = SCNVector3Make( m+q, -m-q, m+q)
return [topLeft, topRight, bottomLeft, bottomRight]
}
private func cubeFace() -> SCNGeometry {
let vertices : [SCNVector3] = squareVertices(l)
let geoSrc = SCNGeometrySource(vertices: UnsafePointer<SCNVector3>(vertices), count: vertices.count)
// index buffer
let idx1 : [Int32] = [0, 3]
let data1 = NSData(bytes: idx1, length: (sizeof(Int32) * idx1.count))
let geoElements1 = SCNGeometryElement(data: data1, primitiveType: SCNGeometryPrimitiveType.Line, primitiveCount: idx1.count, bytesPerIndex: sizeof(Int32))
let idx2 : [Int32] = [1, 2]
let data2 = NSData(bytes: idx2, length: (sizeof(Int32) * idx2.count))
let geoElements2 = SCNGeometryElement(data: data2, primitiveType: SCNGeometryPrimitiveType.Line, primitiveCount: idx2.count, bytesPerIndex: sizeof(Int32))
let geo = SCNGeometry(sources: [geoSrc], elements: [geoElements1, geoElements2])
return geo
}
private func setupFaceNodes() {
// sides
for i in 0..<4 {
let face = SCNNode(geometry: cubeFace())
face.rotation = SCNVector4Make(0, 1, 0, Float(i) * Float(M_PI_2))
rootNode.addChildNode(face)
}
// top/bottom
for i in [1, 3] {
let face = SCNNode(geometry: cubeFace())
face.rotation = SCNVector4Make(1, 0, 0, Float(i) * Float(M_PI_2))
rootNode.addChildNode(face)
}
}
I have something that looks like this with the correct overall shape:
but I can't figure out how to increase the width of the lines being drawn using SceneKit. How can I achieve this?
For those interested, here is a sample proj.
SceneKit doesn't provide controls for this. However, SceneKit draws using OpenGL ES, which does.
When you're drawing with GL in the GL_LINES
mode, the glLineWidth
call changes the line width. (Watch out: the argument is in actual pixels, not UI-layout points, so you'll need a larger width than you might think if you don't want super-thin hairlines on a Retina display.)
So, where do you call that in your SceneKit app? You have a few options there. In a simple scene like yours, where you're only rendering one thing, you can just set it before the scene renders. Set a delegate for your view, then implement renderer:willRenderSceneAtTime:
and call glLineWidth
there.
However, OpenGL line rendering is pretty limited — if you want to customize rendering more, you'll need a different approach. Just which approach works best depends on exactly what you're going for, so here are a few ideas for you to research: