我正在尝试制作一个游戏,其中给您一个球体,球体的半径和球体表面上的一个点。我使用SceneKit作为基本框架。球体是SCNSphere
,半径是SCNCylinder
,将其仔细放置,使其看起来像球体的半径(圆柱体的高度等于球体的半径,并且位于球体的中心球形)。球体表面上的点是SKScene作为其材质应用在球体表面上。
我的目标是将圆柱体的一端固定在球体的中心,然后旋转圆柱体,使其顶端可以位于球体表面的每个点。
我正在尝试通过使用SCNAction
实现相同的目标,但它远没有我想要的那样。
我的代码是:
struct SceneKitView: UIViewRepresentable {
func makeUIView(context: UIViewRepresentableContext<SceneKitView>) -> SCNView {
//SCNScene
let sceneView = SCNView()
sceneView.scene = SCNScene()
sceneView.allowsCameraControl = true
sceneView.autoenablesDefaultLighting = true
sceneView.backgroundColor = UIColor.white
sceneView.frame = CGRect(x: 0, y: 10, width: 0, height: 1)
//A SKScene used as a material for a Sphere
let surfacematerial = SKScene(size: CGSize(width: 300, height: 200))
let point = SKShapeNode(circleOfRadius: 2)
surfacematerial.backgroundColor = SKColor.blue
point.fillColor = SKColor.red
point.lineWidth = 0
point.position = CGPoint(x: surfacematerial.size.width/2.0, y: surfacematerial.size.height/2.0)
surfacematerial.addChild(point)
//The SCNSphere
let sphere = SCNSphere(radius: CGFloat(2))
let spherematerial = SCNMaterial()
spherematerial.diffuse.contents = surfacematerial
sphere.materials = [spherematerial]
let spherenode = SCNNode(geometry: sphere)
spherenode.position = SCNVector3(x: 1.0, y: 1.0, z: 1.0)
spherenode.opacity = CGFloat(0.6)
//The radius of the sphere( a SCNCylinder )
let cylinder = SCNCylinder(radius: 0.02, height: 2.0)
let cylindernode = SCNNode(geometry: cone)
cylindernode.position = SCNVector3(x: 1, y: 2, z: 1)
cylinder.firstMaterial?.diffuse.contents = UIColor.green
//Rotating the radius
func degreesToRadians(_ degrees: Float) -> CGFloat {
return CGFloat(degrees * .pi / 180)
}
let rotate = SCNAction.rotate(by: degreesToRadians(90.0), around: SCNVector3(x: 1, y: 0 , z: 0), duration: 10)
sceneView.scene?.rootNode.addChildNode(conenode)
sceneView.scene?.rootNode.addChildNode(spherenode)
return sceneView
}
func updateUIView(_ uiView: SCNView, context: UIViewRepresentableContext<SceneKitView>) {
}
typealias UIViewType = SCNView
}
请帮助我解决这个问题。
有几种不同的方法,一旦超过90度的样本,我不清楚您想如何旋转,这会有所不同。
这里是如何使用圆柱体绘制带有矢量的线(搜索桩35002232)。有几个选择,我喜欢这个答案:“ class CylinderLine:SCNNode”并使用了它的一个版本。这样一来,您就可以处理矢量,但每次更改时都必须绘制并删除它们。
如果您有目标节点,也可以尝试采用Lookat方法。如果要移动目标节点(可能是不可见的节点)并让圆柱体跟随它,则此方法效果很好:
baseNode.constraints = []
let vConstraint = SCNLookAtConstraint(target: targetNode)
vConstraint.isGimbalLockEnabled = true
baseNode.constraints = [vConstraint]
最适合于基础节点,然后将圆柱节点添加为子节点,以便将其固定到基础节点。然后,您的baseNode专注于目标,圆柱体将随之自动旋转。
您还必须从正确的位置开始绘制。这是内部带有火管的3D坦克的示例。设置vNode的目标会将所有内容一起旋转。只需将SCNBox更改为Sphere-即可使用。
let BoxGeometry = SCNBox(width: 0.8, height: 0.8, length: 0.8, chamferRadius: 0.0)
let vNode = SCNNode(geometry: BoxGeometry)
BoxGeometry.materials = setDefenseTextures(vGameType: vGameType)
let tubeGeometry = SCNTube(innerRadius: 0.03, outerRadius: 0.05, height: 0.9)
let fireTube = SCNNode(geometry: tubeGeometry)
tubeGeometry.firstMaterial?.diffuse.contents = data.getTextureColor(vTheme: 0, vTextureType: .barrelColor)
fireTube.position = SCNVector3(0, 0.2, -0.3)
let vRotateX = SCNAction.rotateBy(x: CGFloat(Float(GLKMathDegreesToRadians(-90))), y: 0, z: 0, duration: 0)
fireTube.runAction(vRotateX)
vNode.addChildNode(fireTube)