SceneKit Object between two points

给你一囗甜甜゛ 提交于 2019-12-04 15:56:49

问题


Given 2 points in 3D (a,b) and an SCNCapsule, SCNTorus, SCNTube etc., how to go about to position the object, so that the object starts at point a and ends at point b?

Code example in Swift or Objective-C would be appreciated.

From Moustachs answer I managed to do a 2-dimension solution:

var v1 = SCNVector3(x: Float(a.x), y: Float(a.y), z: 0.0)
var v2 = SCNVector3(x: Float(b.x), y: Float(b.y), z: 0.0)

let height = CGFloat(v1.distance(v2))
var capsule = SCNCapsule(capRadius: 0.1, height: height)

var node = SCNNode(geometry: capsule)

var midpoint = (v1 + v2) / 2.0

node.position = midpoint

var rotp = v2 - midpoint

let rotx = atan2( rotp.y, rotp.x )
node.eulerAngles = SCNVector3Make(0.0, 0.0, rotx)

self.addChildNode(node)

I know, that there are infinite many solutions for a complete 3D rotation, but I do not care about the third axis. Still, it seems that even the second axis rotation will not work for me. Maybe my math eludes me. Anyone can tell me how to get this code lifted up to 3D space?

(I am using Swift and Kim Pedersens SCNVector3Extensions: https://github.com/devindazzle/SCNVector3Extensions)


回答1:


I've good news for you ! You can link two points and put a SCNNode on this Vector !

Take this and enjoy drawing line between two points !

class   CylinderLine: SCNNode
{
    init( parent: SCNNode,//Needed to line to your scene
        v1: SCNVector3,//Source
        v2: SCNVector3,//Destination
        radius: CGFloat,// Radius of the cylinder
        radSegmentCount: Int, // Number of faces of the cylinder
        color: UIColor )// Color of the cylinder
    {
        super.init()

        //Calcul the height of our line
        let  height = v1.distance(v2)

        //set position to v1 coordonate
        position = v1

        //Create the second node to draw direction vector
        let nodeV2 = SCNNode()

        //define his position
        nodeV2.position = v2
        //add it to parent
        parent.addChildNode(nodeV2)

        //Align Z axis
        let zAlign = SCNNode()
        zAlign.eulerAngles.x = CGFloat(M_PI_2)

        //create our cylinder
        let cyl = SCNCylinder(radius: radius, height: CGFloat(height))
        cyl.radialSegmentCount = radSegmentCount
        cyl.firstMaterial?.diffuse.contents = color

        //Create node with cylinder
        let nodeCyl = SCNNode(geometry: cyl )
        nodeCyl.position.y = CGFloat(-height/2)
        zAlign.addChildNode(nodeCyl)

        //Add it to child
        addChildNode(zAlign)

        //set constraint direction to our vector
        constraints = [SCNLookAtConstraint(target: nodeV2)]
    }

    override init() {
        super.init()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

private extension SCNVector3{
    func distance(receiver:SCNVector3) -> Float{
        let xd = receiver.x - self.x
        let yd = receiver.y - self.y
        let zd = receiver.z - self.z
        let distance = Float(sqrt(xd * xd + yd * yd + zd * zd))

        if (distance < 0){
            return (distance * -1)
        } else {
            return (distance)
        }
    }
}



回答2:


There is no easy way to do it, but it should not be that hard either. You should implement an algorithm that go through the following steps:

  • Get A & B's position as SCNVector3
  • Figure out the distance, the middle point and the angle between those vector points (it's basic vector math, you can find many code samples online)
  • Create whichever shape you want, with the following size: (assume d is the previously found distance).
    • For SCNCapsule and SCNTube, set height to the distance
    • For SCNTorus, set ringRadius to d/2-pipeRadius
    • For SCNBox, set any side to d
  • Move that shape to the middle-point you found earlier
  • Rotate the shape using the angle between the points (you might have to adjust the axis)

Once you do that, the shape you created should meet the points at both ends. You can check this is correct using a bounding box, making sure the right axis is equal to the distance.

I have no code sample, but give it a try and if it doesn't work I can debug it for you.



来源:https://stackoverflow.com/questions/30190171/scenekit-object-between-two-points

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!