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,但使用实时视频而不是静态图像。
对 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,但使用实时视频而不是静态图像。