Draw SceneKit object between two points

前端 未结 7 1988
别跟我提以往
别跟我提以往 2020-12-07 23:51

Having made some progress in the geometry side of things I\'m moving on to putting together an entire scene. That scene has a couple dozen objects, each defined by a boundin

7条回答
  •  萌比男神i
    2020-12-08 00:11

    Both solutions mentioned above work very well and I can contribute third solution to this question.

    //extension code starts
    
    func normalizeVector(_ iv: SCNVector3) -> SCNVector3 {
        let length = sqrt(iv.x * iv.x + iv.y * iv.y + iv.z * iv.z)
        if length == 0 {
            return SCNVector3(0.0, 0.0, 0.0)
        }
    
        return SCNVector3( iv.x / length, iv.y / length, iv.z / length)
    
    }
    
    extension SCNNode {
    
        func buildLineInTwoPointsWithRotation(from startPoint: SCNVector3,
                                  to endPoint: SCNVector3,
                                  radius: CGFloat,
                                  color: UIColor) -> SCNNode {
            let w = SCNVector3(x: endPoint.x-startPoint.x,
                               y: endPoint.y-startPoint.y,
                               z: endPoint.z-startPoint.z)
            let l = CGFloat(sqrt(w.x * w.x + w.y * w.y + w.z * w.z))
    
            if l == 0.0 {
                // two points together.
                let sphere = SCNSphere(radius: radius)
                sphere.firstMaterial?.diffuse.contents = color
                self.geometry = sphere
                self.position = startPoint
                return self
    
            }
    
            let cyl = SCNCylinder(radius: radius, height: l)
            cyl.firstMaterial?.diffuse.contents = color
    
            self.geometry = cyl
    
            //original vector of cylinder above 0,0,0
            let ov = SCNVector3(0, l/2.0,0)
            //target vector, in new coordination
            let nv = SCNVector3((endPoint.x - startPoint.x)/2.0, (endPoint.y - startPoint.y)/2.0,
                                (endPoint.z-startPoint.z)/2.0)
    
            // axis between two vector
            let av = SCNVector3( (ov.x + nv.x)/2.0, (ov.y+nv.y)/2.0, (ov.z+nv.z)/2.0)
    
            //normalized axis vector
            let av_normalized = normalizeVector(av)
            let q0 = Float(0.0) //cos(angel/2), angle is always 180 or M_PI
            let q1 = Float(av_normalized.x) // x' * sin(angle/2)
            let q2 = Float(av_normalized.y) // y' * sin(angle/2)
            let q3 = Float(av_normalized.z) // z' * sin(angle/2)
    
            let r_m11 = q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3
            let r_m12 = 2 * q1 * q2 + 2 * q0 * q3
            let r_m13 = 2 * q1 * q3 - 2 * q0 * q2
            let r_m21 = 2 * q1 * q2 - 2 * q0 * q3
            let r_m22 = q0 * q0 - q1 * q1 + q2 * q2 - q3 * q3
            let r_m23 = 2 * q2 * q3 + 2 * q0 * q1
            let r_m31 = 2 * q1 * q3 + 2 * q0 * q2
            let r_m32 = 2 * q2 * q3 - 2 * q0 * q1
            let r_m33 = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3
    
            self.transform.m11 = r_m11
            self.transform.m12 = r_m12
            self.transform.m13 = r_m13
            self.transform.m14 = 0.0
    
            self.transform.m21 = r_m21
            self.transform.m22 = r_m22
            self.transform.m23 = r_m23
            self.transform.m24 = 0.0
    
            self.transform.m31 = r_m31
            self.transform.m32 = r_m32
            self.transform.m33 = r_m33
            self.transform.m34 = 0.0
    
            self.transform.m41 = (startPoint.x + endPoint.x) / 2.0
            self.transform.m42 = (startPoint.y + endPoint.y) / 2.0
            self.transform.m43 = (startPoint.z + endPoint.z) / 2.0
            self.transform.m44 = 1.0
            return self
        }
    }
    
    //extension ended.
    
    //in your code, you can like this.
    let twoPointsNode1 = SCNNode()
            scene.rootNode.addChildNode(twoPointsNode1.buildLineInTwoPointsWithRotation(
                from: SCNVector3(1,-1,3), to: SCNVector3( 7,11,7), radius: 0.2, color: .cyan))
    //end
    

    you can reference http://danceswithcode.net/engineeringnotes/quaternions/quaternions.html

    BTW, you will get same result when you use a cylinder to make a line between two points from above 3 methods. But indeed, they will have different normal lines. In another words, if you use box between two points, sides of box, except top and bottom, will face different direction from above 3 methods.

    let me know pls if you need further explanation.

提交回复
热议问题