Skip to content

Instantly share code, notes, and snippets.

@chunkyguy
Last active April 28, 2025 21:57
Show Gist options
  • Save chunkyguy/f01b4b72eac9b85c37bc74488aa8f7fa to your computer and use it in GitHub Desktop.
Save chunkyguy/f01b4b72eac9b85c37bc74488aa8f7fa to your computer and use it in GitHub Desktop.
Cornell Box with SceneKit, which is probably the hello world of Computer Graphics.
import Foundation
import SceneKit
import GLKit
class World {
let scene = SCNScene()
func setUp() {
let worldNode = scene.rootNode
addLights(to: worldNode)
addCamera(to: worldNode)
addScene(to: worldNode)
}
}
private extension World {
private func addCamera(to parent: SCNNode) {
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(0, 0, 1)
cameraNode.look(at: SCNVector3(0, 0, 0))
parent.addChildNode(cameraNode)
}
}
private extension World {
private func addLights(to parent: SCNNode) {
addRoomLight(to: parent)
addSpotLight(to: parent)
}
private func addRoomLight(to parent: SCNNode) {
let light = SCNLight()
light.type = .omni
light.color = UIColor(white: 0.5, alpha: 1).cgColor
let node = SCNNode()
node.light = light
node.position = SCNVector3(0, 0, 1)
parent.addChildNode(node)
}
private func addSpotLight(to parent: SCNNode) {
let light = SCNLight()
light.type = .spot
light.color = UIColor.white.cgColor
light.castsShadow = true
let node = SCNNode()
node.light = light
node.position = SCNVector3(0, 1, 0)
node.look(at: SCNVector3(0, 0, 0))
parent.addChildNode(node)
}
}
private extension World {
private func addScene(to parent: SCNNode) {
addWalls(to: parent)
addCubes(to: parent)
addLightSource(to: parent)
}
}
private extension World {
private func addWalls(to parent: SCNNode) {
let wallColor = UIColor(white: 0.8, alpha: 1)
addWall(
to: parent,
color: wallColor,
position: simd_float3(0, 0, -0.5)
)
addWall(
to: parent,
color: .green,
position: simd_float3(-0.5, 0, 0),
rotation: simd_float4(0, 1, 0, GLKMathDegreesToRadians(90))
)
addWall(
to: parent,
color: .red,
position: simd_float3(0.5, 0, 0),
rotation: simd_float4(0, 1, 0, GLKMathDegreesToRadians(270))
)
addWall(
to: parent,
color: wallColor,
position: simd_float3(0, 0.5, 0),
rotation: simd_float4(1, 0, 0,GLKMathDegreesToRadians(270))
)
addWall(
to: parent,
color: wallColor,
position: simd_float3(0, -0.5, 0),
rotation: simd_float4(1, 0, 0, GLKMathDegreesToRadians(90))
)
}
private func addWall(to parent: SCNNode, color: UIColor, position: simd_float3, rotation: simd_float4 = simd_float4.zero) {
let geometry = SCNPlane(width: 1, height: 1)
let material = SCNMaterial()
material.isDoubleSided = true
material.diffuse.contents = color.cgColor
geometry.materials = [material]
let wall = SCNNode(geometry: geometry)
wall.simdPosition = position
wall.simdRotation = rotation
parent.addChildNode(wall)
}
}
private extension World {
private func addCubes(to parent: SCNNode) {
addCube(
to: parent,
height: 0.6,
positionX: -0.2,
positionZ: -0.5,
rotation: 20
)
addCube(
to: parent,
height: 0.3,
positionX: 0.1,
positionZ: -0.25,
rotation: -25
)
}
private func addCube(to parent: SCNNode, height: CGFloat, positionX: CGFloat, positionZ: CGFloat, rotation: CGFloat) {
let cubeGeo = SCNBox(width: 0.3, height: height, length: 0.3, chamferRadius: 0)
let cubeMat = SCNMaterial()
cubeMat.diffuse.contents = UIColor.lightGray.cgColor
cubeGeo.materials = [cubeMat]
let cube = SCNNode(geometry: cubeGeo)
cube.position = SCNVector3(positionX, -0.5 + height/2.0, positionZ)
cube.rotation = SCNVector4(0, 1, 0, GLKMathDegreesToRadians(Float(rotation)))
parent.addChildNode(cube)
}
}
private extension World {
private func addLightSource(to parent: SCNNode) {
let geometry = SCNPlane(width: 0.05, height: 0.05)
let material = SCNMaterial()
material.isDoubleSided = true
material.emission.contents = UIColor.white.cgColor
geometry.materials = [material]
let node = SCNNode(geometry: geometry)
node.position = SCNVector3(0, 0.49, 0)
node.rotation = SCNVector4(1, 0, 0, GLKMathDegreesToRadians(270))
parent.addChildNode(node)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment