【问题标题】:Scenekit - How to keep a line between two variable pointScenekit - 如何在两个变量点之间保持一条线
【发布时间】:2022-01-25 01:43:30
【问题描述】:

我需要在两个可变点之间画一条线,并且我必须不断更新线的几何形状以使其保持正确的位置、旋转和高度。

我尝试了下面的代码,但由于更新调用过多,该行闪烁:

class Line: SCNNode {
    
    var color       : UIColor
    var radius      : CGFloat
    
    init(from start: SCNVector3, to end: SCNVector3, color: UIColor = .yellow, radius: CGFloat = 0.002) {
        
        self.color = color
        self.radius = radius
        
        super.init()
        
        updateGeometry(from: start, to: end)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func updateGeometry(from start: SCNVector3, to end: SCNVector3) {
        
        //Initial geometry once
        if geometry == nil {
            let geometry = SCNCylinder()
            
            let material = SCNMaterial()
            material.diffuse.contents = color
            geometry.materials = [material]
            geometry.radius = radius
            
            self.geometry = geometry
        }
        
        guard let geometry = geometry as? SCNCylinder else { return }
        
        let vector = SCNVector3(start.x - end.x, start.y - end.y, start.z - end.z)
        
        let height = CGFloat(sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z))
        let position = SCNVector3 (x:(start.x + end.x) / 2, y: (start.y + end.y) / 2, z:(start.z + end.z) / 2)
        
        //Prevent unnecessary geometry update
        guard !SCNVector3EqualToVector3(position, self.position) || geometry.height != height else { return }
        
        geometry.height = height
        
        self.position = position
        look(at: end, up: SCNVector3(0, 1, 0), localFront: worldUp)
    }
}

//Call updateGeometry in update method to make sure it is in correct shape
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
        updateFloatingLine()
}

【问题讨论】:

    标签: ios swift scenekit


    【解决方案1】:

    发布 [21886224] - 如果您没有太多圆柱体方法,可以尝试使用圆柱体方法。我不确定它会解决闪烁问题...

    我的版本...通过许多帖子将其放在一起。我已经很久没有这样做了,所以我不记得一切,只是我没有用几何解决它。它用于发射激光(源到目标),所以我不知道它如何满足您的需求,但也许您可以尝试一下。祝你好运

    let x = SCNNode().buildLineInTwoPointsWithRotation(from: SCNVector3(-vX, vY, vZ), to: SCNVector3(vX, vY, vZ), radius: 0.2, color: UIColor.blue)
            gameNodes.addChildNode(x)
    
    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
        }
    

    【讨论】:

    • 谢谢,但没用,你的代码比较重,因为你不必每次都构建节点和几何,更新几何就足够了。
    猜你喜欢
    • 2020-02-16
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多