将SCNMatrix 4从swift转换为Objective-c

np8igboo  于 2023-01-08  发布在  Swift
关注(0)|答案(1)|浏览(125)

我一辈子都想不出如何从objective-c中的转换创建SCNMatrix4。
我尝试在objective-c中使用的swift代码:

let affineTransform = frame.displayTransform(for: .portrait, viewportSize: sceneView.bounds.size)
let transform = SCNMatrix4(affineTransform)
faceGeometry.setValue(SCNMatrix4Invert(transform), forKey: "displayTransform")

我得到了第一行和第三行,但我找不到从CGAffineTransform创建此SCNMatrix4的方法。

CGAffineTransform affine = [self.sceneView.session.currentFrame displayTransformForOrientation:UIInterfaceOrientationPortrait viewportSize:self.sceneView.bounds.size];
SCNMatrix4 trans = ??
[f setValue:SCNMatrix4Invert(trans) forKey:@"displayTransform"];

没有SCNMatrix4Make,我尝试了simd_matrix4x4,但似乎也不起作用。
谢谢
编辑:
swift的代码来自苹果的Example项目"ARKitFaceExample",以下是完整的代码:

/*
See LICENSE folder for this sample’s licensing information.

Abstract:
Demonstrates using video imagery to texture and modify the face mesh.
*/

import ARKit
import SceneKit

/// - Tag: VideoTexturedFace
class VideoTexturedFace: TexturedFace {
    
    override func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
        guard let sceneView = renderer as? ARSCNView,
            let frame = sceneView.session.currentFrame,
            anchor is ARFaceAnchor
            else { return nil }
        
        #if targetEnvironment(simulator)
        #error("ARKit is not supported in iOS Simulator. Connect a physical iOS device and select it as your Xcode run destination, or select Generic iOS Device as a build-only destination.")
        #else
        // Show video texture as the diffuse material and disable lighting.
        let faceGeometry = ARSCNFaceGeometry(device: sceneView.device!, fillMesh: true)!
        let material = faceGeometry.firstMaterial!
        material.diffuse.contents = sceneView.scene.background.contents
        material.lightingModel = .constant

        guard let shaderURL = Bundle.main.url(forResource: "VideoTexturedFace", withExtension: "shader"),
            let modifier = try? String(contentsOf: shaderURL)
            else { fatalError("Can't load shader modifier from bundle.") }
        faceGeometry.shaderModifiers = [ .geometry: modifier]

        // Pass view-appropriate image transform to the shader modifier so
        // that the mapped video lines up correctly with the background video.
        let affineTransform = frame.displayTransform(for: .portrait, viewportSize: sceneView.bounds.size)
        let transform = SCNMatrix4(affineTransform)
        faceGeometry.setValue(SCNMatrix4Invert(transform), forKey: "displayTransform")

        contentNode = SCNNode(geometry: faceGeometry)
        #endif
        return contentNode
    }
    
}

如果有人需要这个,这是我丢失的分机号

extension SCNMatrix4 {
    /**
     Create a 4x4 matrix from CGAffineTransform, which represents a 3x3 matrix
     but stores only the 6 elements needed for 2D affine transformations.
     
     [ a  b  0 ]     [ a  b  0  0 ]
     [ c  d  0 ]  -> [ c  d  0  0 ]
     [ tx ty 1 ]     [ 0  0  1  0 ]
     .               [ tx ty 0  1 ]
     
     Used for transforming texture coordinates in the shader modifier.
     (Needs to be SCNMatrix4, not SIMD float4x4, for passing to shader modifier via KVC.)
     */
    init(_ affineTransform: CGAffineTransform) {
        self.init()
        m11 = Float(affineTransform.a)
        m12 = Float(affineTransform.b)
        m21 = Float(affineTransform.c)
        m22 = Float(affineTransform.d)
        m41 = Float(affineTransform.tx)
        m42 = Float(affineTransform.ty)
        m33 = 1
        m44 = 1
    }
}
lbsnaicq

lbsnaicq1#

要复制Swift扩展以从CGAffineTransform创建SCNMatrix4,您可以实现以下函数:
一些.h文件:

extern SCNMatrix4 SCNMatrix4FromTransform(CGAffineTransform transform);

一些.m文件:

SCNMatrix4 SCNMatrix4FromTransform(CGAffineTransform transform) {
    SCNMatrix4 matrix;
    matrix.m11 = transform.a;
    matrix.m12 = transform.b;
    matrix.m21 = transform.c;
    matrix.m22 = transform.d;
    matrix.m41 = transform.tx;
    matrix.m42 = transform.ty;
    matrix.m33 = 1;
    matrix.m44 = 1;

    return matrix;
}

然后你的代码变成:

CGAffineTransform affineTransform = [self.sceneView.session.currentFrame displayTransformForOrientation:UIInterfaceOrientationPortrait viewportSize:self.sceneView.bounds.size];
SCNMatrix4 transform = SCNMatrixFromTransform(affineTransform);
[f setValue:[NSValue valueWithSCNMatrix4:SCNMatrix4Invert(transform)] forKey:@"displayTransform"];

注意NSValue valueWithSCNMatrix4:的用法,这是将结构体转换为对象所必需的,并且应该满足使用KVC设置displayTransform属性的要求。

相关问题