Thanks for this help. I have checked and this code seems to only produce positive values (and my current "base" node is at 0, 0, 0. Here is my code for anyone to play with/comment on:
import UIKit
import QuartzCore
import SceneKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
/
let scene = SCNScene()
/
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
/
cameraNode.position = SCNVector3(x: 0, y: 0, z: 60)
/
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = SCNLightTypeOmni
lightNode.position = SCNVector3(x: 0, y: 100, z: 100)
scene.rootNode.addChildNode(lightNode)
/
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = SCNLightTypeAmbient
ambientLightNode.light!.color = UIColor.darkGrayColor()
scene.rootNode.addChildNode(ambientLightNode)
/
let sphereNode = createSphere(1.0, color: UIColor.blueColor(), x: 0, y: 0, z: 0, name: "First Sphere")
scene.rootNode.addChildNode(sphereNode)
/
let secondSphereNode = createSphere(1.0, color: UIColor.greenColor(), x: Float(1+arc4random_uniform(3)), y: Float(1+arc4random_uniform(3)), z: Float(1+arc4random_uniform(3)), name: "Second Sphere")
scene.rootNode.addChildNode(secondSphereNode)
/
let lineNode = lineBetweenNodes(sphereNode, nodeB: secondSphereNode)
scene.rootNode.addChildNode(lineNode)
/
let scnView = self.view as! SCNView
/
scnView.scene = scene
/
scnView.backgroundColor = UIColor.blackColor()
/* Removed gesture recoginizer stuff here
}
func cylinderBetweenNodes(nodeA: SCNNode, nodeB: SCNNode, radius: CGFloat = 0.3, lineColor: UIColor = UIColor.yellowColor()) -> SCNNode
{
let height = sqrtf(pow(nodeA.position.x - nodeB.position.x,2) + pow(nodeA.position.y - nodeB.position.y,2) + pow(nodeA.position.z - nodeB.position.z,2))
let cylinder = SCNCylinder(radius: radius, height: CGFloat(height))
cylinder.firstMaterial?.diffuse.contents = lineColor
let cylinderNode = SCNNode(geometry: cylinder)
cylinderNode.position = SCNVector3Make((nodeB.position.x - nodeA.position.x)/2 + nodeA.position.x, (nodeB.position.y - nodeA.position.y)/2 + nodeA.position.y, (nodeB.position.z - nodeA.position.z)/2 + nodeA.position.z)
cylinderNode.rotation = SCNVector4Make(1.0, 1.0, 0.0, Float(M_PI)/2.0)
return cylinderNode
}
func lineBetweenNodes(nodeA: SCNNode, nodeB: SCNNode, lineWidth: Float = 1, lineColor: UIColor = UIColor.yellowColor()) -> SCNNode {
glLineWidth(lineWidth)
let positions: [Float32] = [nodeA.position.x, nodeA.position.y, nodeA.position.z, nodeB.position.x, nodeB.position.y, nodeB.position.z]
let positionData = NSData(bytes: positions, length: sizeof(Float32)*positions.count)
let indices: [Int32] = [0, 1]
let indexData = NSData(bytes: indices, length: sizeof(Int32) * indices.count)
let source = SCNGeometrySource(data: positionData, semantic: SCNGeometrySourceSemanticVertex, vectorCount: indices.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(Float32), dataOffset: 0, dataStride: sizeof(Float32) * 3)
let element = SCNGeometryElement(data: indexData, primitiveType: SCNGeometryPrimitiveType.Line, primitiveCount: indices.count, bytesPerIndex: sizeof(Int32))
let line = SCNGeometry(sources: [source], elements: [element])
line.firstMaterial?.diffuse.contents = lineColor
return SCNNode(geometry: line)
}
func createSphere(radius: CGFloat, color: UIColor, x: Float, y: Float, z: Float, name: String) -> SCNNode
{
let sphere = SCNSphere(radius: radius)
sphere.firstMaterial?.diffuse.contents = color
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = SCNVector3Make(x, y, z)
sphereNode.physicsBody = SCNPhysicsBody(type: SCNPhysicsBodyType.Kinematic, shape: SCNPhysicsShape(geometry: sphereNode.geometry!, options: nil))
sphereNode.name = name
let text = SCNText(string: sphereNode.name, extrusionDepth: radius / 4.0)
text.firstMaterial?.diffuse.contents = color
let textNode = SCNNode(geometry: text)
textNode.position = SCNVector3Make(-1.6 * Float(radius), -1.6 * Float(radius), 1)
text.font = UIFont(name: "Palatino", size: radius / 2.0)
sphereNode.addChildNode(textNode)
return sphereNode;
}
This is from the scenekit default project. The cylinderBetweenNodes doesn't work at all. It is my attempt to not draw a line but a sphere. I want to be able to calculate the new position and then call createSphere repeatedly until I get all the data visualized. Eventually, I will create a createCube to do the application piece. This is just in proof of concept phase. I will add several hundred spheres in a loop to prove the positioning works when I get a solution.
Thanks!
John