Everything so far
This commit is contained in:
parent
1b4a17dc20
commit
18a92331c9
4 changed files with 83 additions and 21 deletions
|
@ -9,21 +9,35 @@
|
|||
import SceneKit
|
||||
import QuartzCore
|
||||
|
||||
class GameViewController: NSViewController {
|
||||
|
||||
class GameViewController: NSViewController, SCNSceneRendererDelegate {
|
||||
static let numberOfBallsPerSide = 41
|
||||
|
||||
private var balls = [SCNNode]()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
guard let sceneView = view as? SCNView else {
|
||||
fatalError("My view isn't a SCNView!")
|
||||
}
|
||||
sceneView.delegate = self
|
||||
sceneView.rendersContinuously = true
|
||||
sceneView.preferredFramesPerSecond = 30
|
||||
|
||||
// create a new scene
|
||||
let scene = SCNScene(named: "art.scnassets/ship.scn")!
|
||||
let scene = SCNScene(named: "art.scnassets/blank.scn")!
|
||||
|
||||
// create and add a camera to the scene
|
||||
let cameraNode = SCNNode()
|
||||
cameraNode.camera = SCNCamera()
|
||||
let camera = SCNCamera()
|
||||
cameraNode.camera = camera
|
||||
scene.rootNode.addChildNode(cameraNode)
|
||||
|
||||
// place the camera
|
||||
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
|
||||
cameraNode.position = SCNVector3(x: CGFloat(GameViewController.numberOfBallsPerSide / 7),
|
||||
y: 1.5,
|
||||
z: CGFloat(GameViewController.numberOfBallsPerSide / 3))
|
||||
cameraNode.look(at: SCNVector3())
|
||||
|
||||
// create and add a light to the scene
|
||||
let lightNode = SCNNode()
|
||||
|
@ -38,33 +52,44 @@ class GameViewController: NSViewController {
|
|||
ambientLightNode.light!.type = .ambient
|
||||
ambientLightNode.light!.color = NSColor.darkGray
|
||||
scene.rootNode.addChildNode(ambientLightNode)
|
||||
|
||||
// retrieve the ship node
|
||||
let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
|
||||
|
||||
// animate the 3d object
|
||||
ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))
|
||||
|
||||
// retrieve the SCNView
|
||||
let scnView = self.view as! SCNView
|
||||
|
||||
let sphereContainer = SCNNode()
|
||||
scene.rootNode.addChildNode(sphereContainer)
|
||||
|
||||
if let sphere = scene.rootNode.childNode(withName: "sphere", recursively: false) {
|
||||
// Remove it. We're going to copy it all over the place.
|
||||
sphere.removeFromParentNode()
|
||||
for i in 0..<GameViewController.numberOfBallsPerSide {
|
||||
for j in 0..<GameViewController.numberOfBallsPerSide {
|
||||
let ijSphere = sphere.clone()
|
||||
balls.append(ijSphere)
|
||||
ijSphere.worldPosition = SCNVector3(x: CGFloat(-GameViewController.numberOfBallsPerSide / 2) + CGFloat(i),
|
||||
y: 0.0,
|
||||
z: CGFloat(-GameViewController.numberOfBallsPerSide / 2) + CGFloat(j))
|
||||
sphereContainer.addChildNode(ijSphere)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sphereContainer.runAction(SCNAction.repeatForever(SCNAction.rotate(by: CGFloat.pi, around: SCNVector3(0, 1, 0), duration: 40.0)))
|
||||
|
||||
// set the scene to the view
|
||||
scnView.scene = scene
|
||||
sceneView.scene = scene
|
||||
|
||||
// allows the user to manipulate the camera
|
||||
scnView.allowsCameraControl = true
|
||||
sceneView.allowsCameraControl = false
|
||||
|
||||
// show statistics such as fps and timing information
|
||||
scnView.showsStatistics = true
|
||||
sceneView.showsStatistics = true
|
||||
|
||||
// configure the view
|
||||
scnView.backgroundColor = NSColor.black
|
||||
sceneView.backgroundColor = NSColor.black
|
||||
|
||||
// Add a click gesture recognizer
|
||||
let clickGesture = NSClickGestureRecognizer(target: self, action: #selector(handleClick(_:)))
|
||||
var gestureRecognizers = scnView.gestureRecognizers
|
||||
var gestureRecognizers = sceneView.gestureRecognizers
|
||||
gestureRecognizers.insert(clickGesture, at: 0)
|
||||
scnView.gestureRecognizers = gestureRecognizers
|
||||
sceneView.gestureRecognizers = gestureRecognizers
|
||||
}
|
||||
|
||||
@objc
|
||||
|
@ -102,4 +127,41 @@ class GameViewController: NSViewController {
|
|||
SCNTransaction.commit()
|
||||
}
|
||||
}
|
||||
|
||||
func delayForSphereAt(x: Int, y: Int) -> Double {
|
||||
return 0.05 * Double(x) + 0.03 * Double(y)
|
||||
}
|
||||
|
||||
// MARK: - SCNRendererDelegate
|
||||
|
||||
static let numberOfSteps = 100
|
||||
var step = 0
|
||||
var maxY = 0.0
|
||||
var minY = 0.0
|
||||
|
||||
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
|
||||
for z in 0..<GameViewController.numberOfBallsPerSide {
|
||||
for x in 0..<GameViewController.numberOfBallsPerSide {
|
||||
let idx = z * GameViewController.numberOfBallsPerSide + x
|
||||
let node = balls[idx]
|
||||
let delay = delayForSphereAt(x: x, y: z)
|
||||
//let inputX = 2.0 * Double.pi * Double(step) / Double(GameViewController.numberOfSteps) + delay
|
||||
|
||||
let inputX = 2.0 / 3.0 * time + delay
|
||||
let y = sin(inputX) + sin(2.0 * inputX) + sin(4.0 * inputX) + sin(8.0 * inputX)
|
||||
|
||||
node.worldPosition.y = CGFloat(y)
|
||||
|
||||
maxY = max(y, maxY)
|
||||
minY = min(y, minY)
|
||||
let scale = CGFloat(map(y, inMin: minY, inMax: maxY, outMin: 0.0, outMax: 1.0))
|
||||
node.scale = SCNVector3(x: scale, y: scale, z: scale)
|
||||
}
|
||||
}
|
||||
step = (step + 1) % GameViewController.numberOfSteps
|
||||
}
|
||||
|
||||
func map(_ x: Double, inMin: Double, inMax: Double, outMin: Double, outMax: Double) -> Double {
|
||||
return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
|
||||
}
|
||||
}
|
||||
|
|
BIN
Waveform/art.scnassets/blank.scn
Normal file
BIN
Waveform/art.scnassets/blank.scn
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 342 KiB |
Loading…
Add table
Add a link
Reference in a new issue