代码之家  ›  专栏  ›  技术社区  ›  Steve

缩放scnnode及其子级

  •  2
  • Steve  · 技术社区  · 6 年前

    SCNNodes

    func addLabel() {
        let plane = SCNPlane(width: 0.07, height: 0.02)
        plane.cornerRadius = plane.height / 10
    
        let sks = SKScene(size: CGSize(width: plane.width * 10e3, height: plane.height * 10e3))
        sks.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 0.7)
    
        currentLbl = SKLabelNode(text: "")
        currentLbl.fontSize = 110
        currentLbl.fontName = "Helvetica"
        currentLbl.verticalAlignmentMode = .center
        currentLbl.position = CGPoint(x: sks.frame.midX, y: sks.frame.midY)
        currentLbl.fontColor = .white
    
        sks.addChild(currentLbl)
    
        let material = SCNMaterial()
        material.isDoubleSided = true
        material.diffuse.contents = sks
        material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)
    
        plane.materials = [material]
        let node = SCNNode(geometry: plane)
        node.constraints = [SCNBillboardConstraint()]
        node.position = SCNVector3Make(0, 0, 0)
        let (minBound, maxBound) = node.boundingBox
        node.pivot = SCNMatrix4MakeTranslation( (maxBound.x + minBound.x)/2, minBound.y, 0.02/2)
    
        lblNodes.append(node)
        currentLblNode = node
        sceneView.scene.rootNode.addChildNode(node)
    }
    

    var myNodes: [SCNNode] = []
    let s = getMagicScalingNumber()
    

    SCNTransformConstraint() 这是一个选项,我希望有一个如何实现它的示例。


    currentLblNode.scale = SCNVector3Make(s, s, s)
    

    1 回复  |  直到 6 年前
        1
  •  4
  •   BlackMirrorz    6 年前

    您可以将这些内容存储到一个[scnnode]数组中,然后像这样转换这些内容的比例:

    /// Updates The Contents Of Each Node Added To Our NodesAdded Array
    ///
    /// - Parameters:
    ///   - nodes: [SCNNode]
    ///   - pointOfView: SCNNode
    func updateScaleFromCameraForNodes(_ nodes: [SCNNode], fromPointOfView pointOfView: SCNNode){
    
        nodes.forEach { (node) in
    
            //1. Get The Current Position Of The Node
            let positionOfNode = SCNVector3ToGLKVector3(node.worldPosition)
    
            //2. Get The Current Position Of The Camera
            let positionOfCamera = SCNVector3ToGLKVector3(pointOfView.worldPosition)
    
            //3. Calculate The Distance From The Node To The Camera
            let distanceBetweenNodeAndCamera = GLKVector3Distance(positionOfNode, positionOfCamera)
    
            //4. Animate Their Scaling & Set Their Scale Based On Their Distance From The Camera
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.5
            switch distanceBetweenNodeAndCamera {
            case 0 ... 0.5:
                node.simdScale = simd_float3(0.25, 0.25, 0.25)
            case 0.5 ... 1:
                node.simdScale = simd_float3(0.5, 0.5, 0.5)
            case 1 ... 1.5:
                node.simdScale = simd_float3(1, 1, 1)
            case 1.5 ... 2:
                node.simdScale = simd_float3(1.5, 1.5, 1.5)
            case 2 ... 2.5:
                node.simdScale = simd_float3(2, 2, 2)
            case 2.5 ... 3:
                node.simdScale = simd_float3(2.5, 2.5, 2.5)
            default:
                print("Default")
            }
            SCNTransaction.commit()
        }
    
    }
    

    为了更好地将这一点放在上下文中,这里有一个小演示,我将其放在一起:

    //--------------------------
    // MARK: - ARSCNViewDelegate
    //--------------------------
    
    extension ViewController: ARSCNViewDelegate{
    
        func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    
            if !nodesAdded.isEmpty, let currentCameraPosition = self.sceneView.pointOfView {
                updateScaleFromCameraForNodes(nodesAdded, fromPointOfView: currentCameraPosition)
            }
    
        }
    }
    
    class ViewController: UIViewController {
    
         @IBOutlet var sceneView: ARSCNView!
    
         var nodesAdded = [SCNNode]()
    
        //-----------------------
        // MARK: - View LifeCycle
        //-----------------------
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            //1. Generate Our Three Box Nodes
            generateBoxNodes()
    
            //2. Run The Session
            let configuration = ARWorldTrackingConfiguration()
            sceneView.session.run(configuration)
            sceneView.delegate = self
    
        }
    
        /// Generates Three SCNNodes With An SCNBox Geometry & Places Them In A Holder Node
        func generateBoxNodes(){
    
            //1. Create An SCNNode To Hold All Of Our Content
            let holderNode = SCNNode()
    
            //2. Create An Array Of Colours For Each Face
            let colours: [UIColor] = [.red, .green, .blue, .purple, .cyan, .black]
    
            //3. Create An SCNNode Wih An SCNBox Geometry
            let boxNode = SCNNode()
            let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.01)
            boxNode.geometry = boxGeometry
    
            //4. Create A Different Material For Each Face
            var materials = [SCNMaterial]()
    
            for i in 0..<5{
                let faceMaterial = SCNMaterial()
                faceMaterial.diffuse.contents = colours[i]
                materials.append(faceMaterial)
            }
    
            //5. Set The Geometries Materials
            boxNode.geometry?.materials = materials
    
            //6. Create Two More Nodes By Cloning The First One
            let secondBox = boxNode.flattenedClone()
            let thirdBox = boxNode.flattenedClone()
    
            //7. Position Them In A Line & Add To The Scene
            boxNode.position = SCNVector3(-0.2, 0, 0)
            secondBox.position = SCNVector3(0, 0, 0)
            thirdBox.position = SCNVector3(0.2, 0, 0)
    
            holderNode.addChildNode(boxNode)
            holderNode.addChildNode(secondBox)
            holderNode.addChildNode(thirdBox)
            holderNode.position = SCNVector3(0, 0, -1)
            self.sceneView.scene.rootNode.addChildNode(holderNode)
    
            nodesAdded.append(holderNode)
        }
    
    
        /// Updates The Contents Of Each Node Added To Our NodesAdded Array
        ///
        /// - Parameters:
        ///   - nodes: [SCNNode]
        ///   - pointOfView: SCNNode
        func updateScaleFromCameraForNodes(_ nodes: [SCNNode], fromPointOfView pointOfView: SCNNode){
    
            nodes.forEach { (node) in
    
                //1. Get The Current Position Of The Node
                let positionOfNode = SCNVector3ToGLKVector3(node.worldPosition)
    
                //2. Get The Current Position Of The Camera
                let positionOfCamera = SCNVector3ToGLKVector3(pointOfView.worldPosition)
    
                //3. Calculate The Distance From The Node To The Camera
                let distanceBetweenNodeAndCamera = GLKVector3Distance(positionOfNode, positionOfCamera)
    
                //4. Animate Their Scaling & Set Their Scale Based On Their Distance From The Camera
                SCNTransaction.begin()
                SCNTransaction.animationDuration = 0.5
                switch distanceBetweenNodeAndCamera {
                case 0 ... 0.5:
                    node.simdScale = simd_float3(0.25, 0.25, 0.25)
                case 0.5 ... 1:
                    node.simdScale = simd_float3(0.5, 0.5, 0.5)
                case 1 ... 1.5:
                    node.simdScale = simd_float3(1, 1, 1)
                case 1.5 ... 2:
                    node.simdScale = simd_float3(1.5, 1.5, 1.5)
                case 2 ... 2.5:
                    node.simdScale = simd_float3(2, 2, 2)
                case 2.5 ... 3:
                    node.simdScale = simd_float3(2.5, 2.5, 2.5)
                default:
                    print("Default")
                }
                SCNTransaction.commit()
            }
    
        }
    
    
        override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) }
    
        override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) }
    
        override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
    
    }