swift 在swift中使用SceneKit制作一个圆柱体
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swift 在swift中使用SceneKit制作一个圆柱体相关的知识,希望对你有一定的参考价值。
//
// GameViewController.swift
// SceneKitTest
//
// Created by Matt Baranowski on 12/19/17.
// Copyright © 2017 Matt Baranowski. All rights reserved.
//
import SceneKit
import QuartzCore
class GameViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
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)!
ship.isHidden = true
let cyclinderNode = SCNNode(geometry: buildCylinder(numSlices: 12, numStacks: 1))
cyclinderNode.name = "cyclinder"
scene.rootNode.addChildNode(cyclinderNode)
let cubeGeometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
let cubeNode = SCNNode(geometry: cubeGeometry)
cubeNode.position = SCNVector3(x: 2.0, y: 0, z: 0)
scene.rootNode.addChildNode(cubeNode)
// 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
// set the scene to the view
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
scnView.debugOptions.insert(SCNDebugOptions.showWireframe)
// configure the view
scnView.backgroundColor = NSColor.lightGray
// Add a click gesture recognizer
let clickGesture = NSClickGestureRecognizer(target: self, action: #selector(handleClick(_:)))
var gestureRecognizers = scnView.gestureRecognizers
gestureRecognizers.insert(clickGesture, at: 0)
scnView.gestureRecognizers = gestureRecognizers
}
func buildCylinder(numSlices: Int, numStacks: Int) -> SCNGeometry {
var verts: [SCNVector3] = []
var normals: [SCNVector3] = []
var texCoords: [CGPoint] = []
var indices: [Int32] = []
let sliceStep: CGFloat = (CGFloat.pi * 2) / CGFloat(numSlices)
var sliceAngle: CGFloat = 0
var capCenterVert: Int32 = 0
verts.append(SCNVector3(x: 0, y: 0, z: 0))
normals.append(SCNVector3(x: 0, y: 0, z: -1))
texCoords.append(CGPoint(x: 0, y: 0))
for index in 1...Int32(numSlices) {
verts.append(SCNVector3(x: cos(sliceAngle), y: sin(sliceAngle), z: 0))
normals.append(SCNVector3(x: 0, y: 0, z: -1))
texCoords.append(CGPoint(x: cos(sliceAngle), y: sin(sliceAngle)))
let triangle: [Int32] = [capCenterVert, index, index == numSlices ? (capCenterVert+1) : index+1 ]
indices.append(contentsOf: triangle)
sliceAngle += sliceStep
}
// top cap
capCenterVert = Int32(verts.count)
verts.append(SCNVector3(x: 0, y: 0, z: 1))
normals.append(SCNVector3(x: 0, y: 0, z: 1))
texCoords.append(CGPoint(x: 0, y: 0))
sliceAngle = 0
for index in 1...Int32(numSlices) {
verts.append(SCNVector3(x: cos(sliceAngle), y: sin(sliceAngle), z: 1))
normals.append(SCNVector3(x: 0, y: 0, z: 1))
texCoords.append(CGPoint(x: cos(sliceAngle), y: sin(sliceAngle)))
let triangle: [Int32] = [capCenterVert, capCenterVert + index, index == numSlices ? (capCenterVert+1) : capCenterVert+index+1 ]
indices.append(contentsOf: triangle)
sliceAngle += sliceStep
}
// TODO: sides
let vertSrc = SCNGeometrySource(vertices: verts)
let normalSrc = SCNGeometrySource(normals: normals)
let texCoordSrc = SCNGeometrySource(textureCoordinates: texCoords)
let elementSrc = SCNGeometryElement(indices: indices, primitiveType: .triangles)
let geometry = SCNGeometry(sources: [vertSrc, normalSrc, texCoordSrc], elements: [elementSrc])
let material = SCNMaterial()
material.diffuse.contents = NSColor.red
material.isDoubleSided = true
material.emission.contents = NSColor.red
geometry.firstMaterial = material
return geometry
}
@objc
func handleClick(_ gestureRecognizer: NSGestureRecognizer) {
// retrieve the SCNView
let scnView = self.view as! SCNView
// check what nodes are clicked
let p = gestureRecognizer.location(in: scnView)
let hitResults = scnView.hitTest(p, options: [:])
// check that we clicked on at least one object
if hitResults.count > 0 {
// retrieved the first clicked object
let result = hitResults[0]
// get its material
let material = result.node.geometry!.firstMaterial!
// highlight it
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5
// on completion - unhighlight
SCNTransaction.completionBlock = {
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5
material.emission.contents = NSColor.black
SCNTransaction.commit()
}
material.emission.contents = NSColor.red
SCNTransaction.commit()
}
}
}
以上是关于swift 在swift中使用SceneKit制作一个圆柱体的主要内容,如果未能解决你的问题,请参考以下文章
如何将 SCNFloor 的属性与 Swift 和 Scenekit 一起使用?
在 Swift SceneKit 中使用 CAKeyframeAnimation 为 SCN 对象设置动画
在 SCNSphere 上获取点击位置 - Swift (SceneKit) / iOS