SceneKit Object between two points

前端 未结 2 1629
不知归路
不知归路 2021-02-11 09:58

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 poin

相关标签:
2条回答
  • 2021-02-11 10:17

    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)
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-11 10:24

    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.

    0 讨论(0)
提交回复
热议问题