3
votes

I'm creating multiple nodes automatically and I want to arrange them around me, because at the moment I'm just increasing of 0.1 the current X location.

capsuleNode.geometry?.firstMaterial?.diffuse.contents = imageView
capsuleNode.position = SCNVector3(self.counterX, self.counterY, self.counterZ)
capsuleNode.name = topic.name
self.sceneLocationView.scene.rootNode.addChildNode(capsuleNode)
self.counterX += 0.1

So the question is, how can I have all of them around me instead of just in one line?

Did someone of you have some math function for this? Thank you!

2
I saw stackoverflow.com/questions/30064816/… which feels like something you could use to get the positions for the circle.. Basically you create a circle with bezier path and then you can select certain points where you want to place themVollan
Did you check my ARKIT answer ?Prashant Tukadiya
I'm going to try both of the answersPietro Messineo
@PietroMessineo Just copy paste the func arrangeNode(nodes:[SCNNode]) pass your array you're donePrashant Tukadiya

2 Answers

2
votes

Use this code (macOS version) to test it:

import SceneKit

class GameViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = SCNScene()
        let scnView = self.view as! SCNView
        scnView.scene = scene
        scnView.allowsCameraControl = true
        scnView.backgroundColor = NSColor.black

        for i in 1...12 {  // HERE ARE 12 SPHERES

            let sphereNode = SCNNode(geometry: SCNSphere(radius: 1))
            sphereNode.position = SCNVector3(0, 0, 0)

            // ROTATE ABOUT THIS OFFSET PIVOT POINT
            sphereNode.simdPivot.columns.3.x = 5
            sphereNode.geometry?.firstMaterial?.diffuse.contents = NSColor(calibratedHue: CGFloat(i)/12, 
                                                                              saturation: 1, 
                                                                              brightness: 1,                
                                                                                   alpha: 1)

            // ROTATE ABOUT Y AXIS (STEP is 30 DEGREES EXPRESSED IN RADIANS)
            sphereNode.rotation = SCNVector4(0, 1, 0, (-CGFloat.pi * CGFloat(i))/6)
            scene.rootNode.addChildNode(sphereNode)
        }
    }
}

enter image description here

enter image description here

P.S. Here's a code for creating 90 spheres:

for i in 1...90 {

    let sphereNode = SCNNode(geometry: SCNSphere(radius: 0.1))
    sphereNode.position = SCNVector3(0, 0, 0)
    sphereNode.simdPivot.columns.3.x = 5
    sphereNode.geometry?.firstMaterial?.diffuse.contents = NSColor(calibratedHue: CGFloat(i)/90, saturation: 1, brightness: 1, alpha: 1)
    sphereNode.rotation = SCNVector4(0, 1, 0, (-CGFloat.pi * (CGFloat(i))/6)/7.5)
    scene.rootNode.addChildNode(sphereNode)
}

enter image description here

1
votes

You need some math here

How I prepare the circle nodes

    var nodes = [SCNNode]()
    for i in  1...20 {
        let node = createSphereNode(withRadius: 0.05, color: .yellow)
        nodes.append(node)
        node.position = SCNVector3(0,0,-1 * 1 / i)
        scene.rootNode.addChildNode(node)
    }

    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        self.arrangeNode(nodes: nodes)
    }


   func createSphereNode(withRadius radius: CGFloat, color: UIColor) -> SCNNode {
        let geometry = SCNSphere(radius: radius)
        geometry.firstMaterial?.diffuse.contents = color
        let sphereNode = SCNNode(geometry: geometry)
        return sphereNode
   }

Math behind arrange the view into circle

func arrangeNode(nodes:[SCNNode]) {

        let radius:CGFloat = 1;

        let angleStep = 2.0 * CGFloat.pi / CGFloat(nodes.count)

        var count:Int = 0

        for node in nodes {
            let xPos:CGFloat = CGFloat(self.sceneView.pointOfView?.position.x ?? 0) + CGFloat(cosf(Float(angleStep) * Float(count))) * (radius - 0)
            let zPos:CGFloat = CGFloat(self.sceneView.pointOfView?.position.z ?? 0) + CGFloat(sinf(Float(angleStep) * Float(count))) * (radius - 0)

            node.position = SCNVector3(xPos, 0, zPos)

            count = count + 1
        }


    }

Note: In third image I have set.

            let xPos:CGFloat =  -1 + CGFloat(cosf(Float(angleStep) * Float(count))) * (radius - 0)
            let zPos:CGFloat = -1 + CGFloat(sinf(Float(angleStep) * Float(count))) * (radius - 0)

That means if you need view around the camera then

use CGFloat(self.sceneView.pointOfView?.position.x ?? 0) or at the random place then provide the value

Output

enter image description here enter image description here

enter image description here