SceneKit:在父级内部垂直居中缩放 SCNNode? [英] SceneKit: vertically center scaled SCNNode inside parent?

查看:64
本文介绍了SceneKit:在父级内部垂直居中缩放 SCNNode?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是缩放 SCNNode 并将其垂直居中在其父级内.

The goal is to scale a SCNNode and vertically center it within its parent.

但是,缩放 SCNNode 不会影响其边界框,并且无法计算缩放高度.如果没有准确的高度,你怎么能让节点在其父节点内垂直居中?

However, scaling a SCNNode does not affect its bounding box and computing the scaled height does not work. Without an accurate height, how can you vertically center the node inside its parent?

要说明使用缩放高度的问题,请参阅附件Tiki.dae.资产的原始高度(如边界框所示)为 324.36.但是,如果将 Y 比例设置为 0.01,则高度不会变为 ~3.24.它变得小于 3,您可以通过将其舒适地安装在高度为 3(半径为 1.5)的球体中来证明这一点.

To illustrate the problem with using the scaled height, see the attached file, Tiki.dae. The original height of the asset (as shown by the bounding box) is 324.36. If you set the Y-scale to 0.01, however, the height doesn't become ~3.24. It becomes smaller than 3, which you can prove by fitting it comfortably within a sphere of height 3 (radius of 1.5).

下面的代码试图将缩放节点置于其父节点的中心,但不起作用.

The code below attempts to center a scaled node inside its parent, but it doesn't work.

注意:参考节点是 WWDC 2015 fox 演示中的 fox/panda 参考节点.

Note: reference node is the fox/panda reference node from the WWDC 2015 fox demo.

            // Create reference node
            let referenceNode = SCNReferenceNode(URL: referenceURL)
            referenceNode?.load()

            // Scale reference node
            let scale = Float(3)
            referenceNode?.scale = SCNVector3(x: scale, y: scale, z: scale)

            // Create geometry for sphere
            let sphereGeometry = SCNSphere(radius: (gridSphere.geometry as! SCNSphere).radius)
            //sphereGeometry.materials = gridSphere.geometry!.materials
            sphereGeometry.firstMaterial!.diffuse.contents = gPurpleColor

            // Create sphere to hold reference node, position at same place as <gridSphere>
            let liveSphere = SCNNode(geometry: sphereGeometry)
            liveSphere.position = gridSphere.position

            // Center reference node inside <liveSphere>
            var min = SCNVector3Zero
            var max = SCNVector3Zero
            referenceNode?.getBoundingBoxMin(&min, max: &max)
            let referenceNodeHeight = max.y - min.y
            referenceNode?.position = SCNVector3(x: 0, y: 0 - referenceNodeHeight, z: 0)

            // Add reference node to <liveSphere>
            liveSphere.addChildNode(referenceNode!)

            // This value never changes no matter the scale value???
            print(referenceNodeHeight)

推荐答案

这是一个 Playground,它添加了一个立方体(代替您的参考节点)作为球体的子级.立方体响应缩放(请参阅//缩放参考节点"后面的行).

Here's a Playground that adds a cube (in place of your reference node) as a child of the sphere. The cube responds to scaling (see the lines following "// Scale reference node").

//: Playground - noun: a place where people can play

import Cocoa
import SceneKit
import XCPlayground

public class GizmoNode: SCNNode {

    required public override init() {
        super.init()
        let axisLength = CGFloat(3.0)
        let offset = CGFloat(axisLength/2.0)
        let axisSide = CGFloat(0.2)
        let chamferRadius = CGFloat(axisSide)

        let xBox = SCNBox(width: axisLength, height: axisSide, length: axisSide, chamferRadius: chamferRadius)
        xBox.firstMaterial?.diffuse.contents = NSColor.redColor()
        let yBox = SCNBox(width: axisSide, height: axisLength, length: axisSide, chamferRadius: chamferRadius)
        yBox.firstMaterial?.diffuse.contents = NSColor.greenColor()
        let zBox = SCNBox(width: axisSide, height: axisSide, length: axisLength, chamferRadius: chamferRadius)
        zBox.firstMaterial?.diffuse.contents = NSColor.blueColor()
        let xNode = SCNNode(geometry: xBox)
        let yNode = SCNNode(geometry: yBox)
        let zNode = SCNNode(geometry: zBox)
        self.addChildNode(xNode)
        self.addChildNode(yNode)
        self.addChildNode(zNode)
        print (xNode.position)
        print (yNode.position)
        print (zNode.position)
        xNode.position.x = offset
        yNode.position.y = offset
        zNode.position.z = offset
        print (xNode.pivot)
        print (yNode.pivot)
        print (zNode.pivot)
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

let sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
let scene = SCNScene()

sceneView.scene = scene
sceneView.backgroundColor = NSColor.blackColor()
sceneView.allowsCameraControl = true

let gizmo = GizmoNode()
scene.rootNode.addChildNode(gizmo)

XCPlaygroundPage.currentPage.liveView = sceneView

// Create reference node
let cubeSize = CGFloat(0.5)
let cubeGeometry = SCNBox(width: cubeSize, height: cubeSize, length: cubeSize, chamferRadius: 0.0)
let referenceNodeStandIn = SCNNode(geometry: cubeGeometry)
//referenceNodeStandIn?.load()
let cubeColor = NSColor.whiteColor().colorWithAlphaComponent(0.5)
cubeGeometry.firstMaterial!.diffuse.contents = cubeColor

// Scale reference node
let scale = CGFloat(8)
referenceNodeStandIn.scale = SCNVector3(x: scale, y: scale, z: scale)

// Create geometry for sphere
let sphereRadius = CGFloat(2.0)
let sphereGeometry = SCNSphere(radius: sphereRadius)
//sphereGeometry.materials = gridSphere.geometry!.materials
let gPurpleColor = NSColor.purpleColor().colorWithAlphaComponent(1.0)
sphereGeometry.firstMaterial!.diffuse.contents = gPurpleColor

// Create sphere to hold reference node, position at same place as <gridSphere>
let liveSphere = SCNNode(geometry: sphereGeometry)
//liveSphere.position = gridSphere.position
scene.rootNode.addChildNode(liveSphere)

// Center reference node inside <liveSphere>
var min = SCNVector3Zero
var max = SCNVector3Zero
referenceNodeStandIn.getBoundingBoxMin(&min, max: &max)
print("min: \(min) max: \(max)")
let referenceNodeHeight = max.y - min.y
//referenceNodeStandIn.position = SCNVector3(x: 0, y: 0 - referenceNodeHeight, z: 0)

// Add reference node to <liveSphere>
liveSphere.addChildNode(referenceNodeStandIn)

// This value never changes no matter the scale value because it's in local coordinate space
print("reference node height", referenceNodeHeight)

这篇关于SceneKit:在父级内部垂直居中缩放 SCNNode?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆