【问题标题】:SceneKit Plane RotationSceneKit 平面旋转
【发布时间】:2018-06-05 12:16:07
【问题描述】:

当我在SceneKit 中创建平面时,平面的法向量默认为正 z 轴。我想通过使用不同的法线向量来重新定位平面。但是,我不确定如何将平面旋转到正确的位置,即使我知道新的法向量应该是什么。想法?

【问题讨论】:

    标签: ios scenekit


    【解决方案1】:

    以下是基于输入 SCNVector3 'axis'(这将是您的目标法线)创建旋转矩阵的示例。

            SCNVector3 tangent0 = [self crossVector: axis: SCNVector3Make(1, 0, 0)];
            if ([self dotVector:tangent0 : tangent0] < 0.001) {
                tangent0 = [self crossVector: axis: SCNVector3Make(0, 1, 0)];
            }
            tangent0 = [self normalizeVector:tangent0];
            SCNVector3 tangent1 = [self normalizeVector: [self crossVector:axis: tangent0]];
    
            GLKVector4 tangent0GLK = GLKVector4Make(tangent0.x, tangent0.y, tangent0.z, 0);
            GLKVector4 tangent1GLK = GLKVector4Make(tangent1.x, tangent1.y, tangent1.z, 0);
            GLKVector4 axisGLK = GLKVector4Make(axis.x, axis.y, axis.z, 0);
    
            rotMat = GLKMatrix4MakeWithColumns(tangent0GLK, tangent1GLK, axisGLK, GLKVector4Make(0, 0, 0, 1));
    

    然后您可以使用乘法将其应用于平面节点的变换属性:

    _node.transform = SCNMatrix4Mult(transmat, SCNMatrix4FromGLKMatrix4( rotMat)) );
    

    以上来自我正在做的一个项目,没有单独测试过。不包括 cross、dot 和 normalizeVector。

    【讨论】:

    • 不,我在 Swift 中没有这个,但它在 Swift 中非常相似,并且可能更简洁一些,具体取决于您用于向量和矩阵数学的数学库。
    【解决方案2】:

    感谢 Xartex 为您的帖子。我用 Swift 重新编码了它。刚开始使用 Swift,所以可能整个事情会更有效率,但它确实有效 :)

    只出现了一个问题,平面的位置也移动了,这不应该的,所以我在变换动作后再次设置了旧位置。

      func SCNVector3CrossProduct(left: SCNVector3, right: SCNVector3) -> SCNVector3 {
            return SCNVector3Make(left.y * right.z - left.z * right.y, left.z * right.x - left.x * right.z, left.x * right.y - left.y * right.x)
        }
    
        func SCNVector3DotProduct(left: SCNVector3, right: SCNVector3) -> float_t {
            return (left.x * right.x + left.y * right.y + left.z * right.z)
        }
    
        func SCNVektor3Normalize(vector: SCNVector3) -> SCNVector3 {
            let scale = 1.0 / sqrt(vector.x*vector.x + vector.y*vector.y + vector.z*vector.z)
    
            return SCNVector3Make(vector.x * scale, vector.y * scale, vector.z*scale)
        }
        let plane2Node = SCNNode(geometry: planeGeometry)
        let plane2Position = SCNVector3(x:0.0, y:0, z:-0.5)
        plane2Node.position = plane2Position
    
    
        let normalVector = SCNVector3Make(0.5, 0, 0)
        let transVector1 = SCNVector3Make(1,0,0)
        let transVector2 = SCNVector3Make(0,1,0)
        var tangent0 = SCNVector3CrossProduct(left: normalVector, right: transVector1)
        let dotprod = SCNVector3DotProduct(left: tangent0, right: tangent0)
        if dotprod < 0.001 {
            tangent0 = SCNVector3CrossProduct(left: normalVector, right: transVector2)
        }
        tangent0 = SCNVektor3Normalize(vector: tangent0)
    
        let helpVector1 = SCNVector3CrossProduct(left: normalVector, right: tangent0)
        let tangent1 = SCNVektor3Normalize(vector: helpVector1)
    
        let tangent0GLK = GLKVector4Make(tangent0.x, tangent0.y, tangent0.z, 0)
        let tangent1GLK = GLKVector4Make(tangent1.x, tangent1.y, tangent1.z, 0)
        let normalGLK = GLKVector4Make(normalVector.x, normalVector.y, normalVector.z, 0);
    
        let rotMat = GLKMatrix4MakeWithColumns(tangent0GLK, tangent1GLK, normalGLK, GLKVector4Make(0, 0, 0, 1))
        // transforms the "normal position" of the plane
        let transMat = SCNMatrix4MakeTranslation(plane2Node.position.x, plane2Node.position.y, plane2Node.position.z);
    
        plane2Node.transform = SCNMatrix4Mult(transMat, SCNMatrix4FromGLKMatrix4( rotMat))
    
        // position must be set again!
        plane2Node.position = plane2Position
    
        scene.rootNode.addChildNode(plane2Node)
    

    【讨论】:

    • 谢谢!我正在尝试解决同样的问题,这确实有效。你能解释一下它背后的数学原理吗,或者我在哪里可以知道它为什么有效。
    猜你喜欢
    • 2018-01-31
    • 2018-12-24
    • 2018-07-17
    • 2018-12-17
    • 2015-02-14
    • 2022-01-12
    • 2017-12-16
    • 2017-07-26
    • 2017-11-30
    相关资源
    最近更新 更多