SceneKit,SCNMaterial的翻转方向

SceneKit, flip direction of SCNMaterial

对 SceneKit 非常陌生,所以在这里寻求帮助:

我有一个 SCNSphere,中间有一个摄像头

我创建了一个 SCNMaterial,doubleSided,并将其分配给球体

由于相机在中心,图像看起来垂直翻转,当里面有文字时完全乱七八糟。

那么如何翻转 material 或图像(尽管稍后将是视频中的帧),欢迎任何其他建议。

这个解决方案,顺便说一句,对我来说是失败的,normalImage 被应用为 material(但是从球体内部看时图像被翻转),但是分配 flippedImage 结果没有 material随便(白屏)

    let normalImage = UIImage(named: "text2.png")
    let ciimage = CIImage(CGImage: normalImage!.CGImage!)
    let flippeCIImage = ciimage.imageByApplyingTransform(CGAffineTransformMakeScale(-1, 1))
    let flippedImage = UIImage(CIImage: flippeCIImage, scale: 1.0, orientation: .Left)

    sceneMaterial.diffuse.contents = flippedImage
    sceneMaterial.specular.contents = UIColor.whiteColor()
    sceneMaterial.doubleSided = true
    sceneMaterial.shininess = 0.5

这对我有用,通过缩放它附加到的节点来翻转几何体的法线:

sphereNode.scale = SCNVector3Make(-1, 1, 1)

您可以使用 SCNMaterialProperty 的 contentsTransform 翻转映射,而不是缩放节点(这可能会破坏您的照明)属性:

material.diffuse.contentsTransform = SCNMatrix4MakeScale(1,-1,1)
material.diffuse.wrapT = SCNWrapModeRepeat // or translate contentsTransform by (0,1,0)

要水平翻转图像:

material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(-1, 1, 1), 1, 0, 0)

垂直翻转:

material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)

已接受的答案不会奏效,我保证。以下是如何翻转指定为 [material].diffuse.contents 属性 值的图像;它假设场景中有两个立方体,side-by-side:

// Define the matrices that perform the two orientation variants
SCNMatrix4 flip_horizontal;
flip_horizontal = SCNMatrix4Translate(SCNMatrix4MakeScale(-1, 1, 1), 1, 0, 0);
SCNMatrix4 flip_vertical;
flip_vertical = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0);

// Create the material objects for each cube, and assign an image as the contents
self.source_material = [SCNMaterial material];
self.source_material.diffuse.contents = [UIImage imageNamed:@"towelface.png"];
self.mirror_material = [SCNMaterial material];
self.mirror_material.diffuse.contents = self.source_material.diffuse.contents;

仅选择以下部分之一(如评论所定义):

// PortraitOpposingDown
    [self.mirror_material.diffuse setContentsTransform:SCNMatrix4Mult(self.source_material.diffuse.contentsTransform, flip_vertical)];
        [self.source_material.diffuse setContentsTransform:SCNMatrix4Mult(self.mirror_material.diffuse.contentsTransform, flip_horizontal)]; 

// PortraitFacingDown
    [self.source_material.diffuse setContentsTransform:SCNMatrix4Mult(self.source_material.diffuse.contentsTransform, flip_vertical)];
    [self.mirror_material.diffuse setContentsTransform:SCNMatrix4Mult(self.source_material.diffuse.contentsTransform, flip_horizontal)];

// PortraitOpposingUp
    [self.source_material.diffuse setContentsTransform:SCNMatrix4Mult(self.source_material.diffuse.contentsTransform, flip_horizontal)];

// PortraitFacingUp
    [self.mirror_material.diffuse setContentsTransform:SCNMatrix4Mult(self.source_material.diffuse.contentsTransform, flip_horizontal)];

在所需索引处插入 material:

[cube[0] insertMaterial:self.source_material atIndex:0];
[cube[1] insertMaterial:self.mirror_material atIndex:0];

顺便说一句,要插入新图像(例如用于实时视频),只需在 insertMaterial:atIndex 方法指定的索引处替换 material;不要重新定位 contentsTransform。以下代码向您展示了如何;它假定您的摄像机配置为将它捕获的每个帧的样本缓冲区输出到 AVCaptureVideoDataOutputSampleBufferDelegate,以及从 [=19] 创建 CGImage 的必要代码 (CreateCGImageFromCVPixelBuffer) =]:

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CGImageRef cgImage;
    CreateCGImageFromCVPixelBuffer(pixelBuffer, &cgImage);
    UIImage *image = [UIImage imageWithCGImage:cgImage];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.source_material.diffuse.contents = image;
        [cube[0] replaceMaterialAtIndex:0 withMaterial:self.source_material];
        self.mirror_material.diffuse.contents = self.source_material.diffuse.contents;
        [cube[1] replaceMaterialAtIndex:0 withMaterial:self.mirror_material];
        });
        CGImageRelease(cgImage);
}

如果您想要实际代码而不是我假设的代码,请询问。 Here's a short video showing this code in action,但使用实时视频而不是静态图像。