如何将scenekit背景的内容设置为立方体贴图

时间:2014-06-22 21:50:31

标签: ios scenekit skybox

我正在尝试使用大约6个图像的数组将场景的背景内容设置为天空盒效果。

我已按正确的顺序创建了图像数组,我知道我需要使用

+ (instancetype) materialPropertyWithContents:(id)contents

但是,我正在努力弄清楚我如何以及在何处使用该类方法来返回包含多维数据集映射的属性。

4 个答案:

答案 0 :(得分:21)

SCNScene"背景" property属于SCNMaterialProperty类。因此,您可以直接将其内容设置为包含6个图像的数组,以设置您的天空盒(参见SCNScene.h)。

aScene.background.contents = @[@"Right.png", @"Left.png", @"Top.png", @"Bottom.png", @"Back.png", @"Front.png"];

确保您的6张图像是正方形且尺寸相同。

答案 1 :(得分:2)

HERES我的awakeFromNib用于ScnView子类

是的,令人困惑的是,分配给内容的值是id而且样本很少。

HERES我的awakeFromNib用于ScnView子类

使用相同尺寸的任何6张图片。 TGA不是必需的。

谷歌天空盒找到例子。

此示例制作了一个天空盒,并将相同的图像应用于立方体,使其看起来像是在天空中。

相机控制已开启,因此只需移动鼠标即可旋转看似镜像的多维数据集

//
//  SkyBoxSceneView.h
//  SceneKit_Skybox
//
//  Created by Brian Clear on 12/06/2014.
//  Copyright (c) 2014 Brian Clear. All rights reserved.
//
#import <SceneKit/SceneKit.h>


@interface SkyBoxSceneView : SCNView

@end



//
//  SkyBoxSceneView.m
//  SceneKit_Skybox
//
//  Created by Brian Clear on 12/06/2014.
//  Copyright (c) 2014 Brian Clear. All rights reserved.
//

#import "SkyBoxSceneView.h"


@implementation SkyBoxSceneView


-(void)awakeFromNib
{
    // create a new scene
    SCNScene *scene = [SCNScene scene];






    //-----------------------------------------------------------------------------------
    //SET THE SKYBOX
    //-----------------------------------------------------------------------------------
    //it took me a while to get it working
    //"APPLE IF YOU WANT SCENE KIT TO SUCCEED YOU NEED A FULL BLOWN GUIDE!!"
    //-----------------------------------------------------------------------------------
    //FIRST ISSUE - Error:scene.background is readonly

     // I misread the help as "to set skybox set the scene.background"
     /*
     scene.background = ;            //INCORRECT
     scene.background.contents = ;   //OK
     */
     //I should have read it as "to set skybox set the scene.background content e.g. scene.background.contents"


    //-----------------------------------------------------------------------------------
    //ONLY EXAMPLE OF setting material.reflective DOESNT WORK for scene.background.content
    /*
     I couldnt get sky box to work for ages because the only example of using reflective property  I found was in
     in the 2014 sample code
     AAPLSlideMaterialLayer.m
     https://developer.apple.com/library/prerelease/mac/samplecode/SceneKitWWDC2014/Listings/Scene_Kit_Session_WWDC_2014_Sources_Slides_AAPLSlideMaterialLayer_m.html#//apple_ref/doc/uid/TP40014551-Scene_Kit_Session_WWDC_2014_Sources_Slides_AAPLSlideMaterialLayer_m-DontLinkElementID_62

     _material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];

     so I tried it on scene.background.contents =

     but didnt work
     */
    //WRONG
    //scene.background.contents = @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"];

    //-----------------------------------------------------------------------------------
    //ATTEMPT 3 - I changed all tga to png but still nothing

    //-----------------------------------------------------------------------------------
    //ATTEMPT 4 - Note this is very wrong. I was way off here
    //when I saw this
    // _material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
    //I then saw this
    //scene.background.contents = ...
    //I made the mistake of presuming that both "content" properties were the same
    //SceneKit take a lot of id properties so WITHOUT A GUIDE you have to guess what goes into thes id properties

    //I though scene.background was a SCNMaterialProperty cos it had scene.background.content
    //same as material.reflective.content - reflective is a SCNMaterialProperty

    //-----------------------------------------------------------------------------------
    //tried it with SCNMaterialProperty.content
    //but would never work as scene.background isnt a SCNMaterialProperty.content
    //    SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents: @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"]];
    //-----------------------------------------------------------------------------------
    //tried with png but same issue
    //    SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents: @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"]];
    //-----------------------------------------------------------------------------------
    //I had tried passing NSImage instead of NSString for material which worked
    //boxNode.geometry.firstMaterial.reflective.contents = @[[NSImage imageNamed:@"right.tga"],....
    //so tried that for scne.background.content
    //but was doomed as not a SCNMaterialProperty
    //    SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents:  @[[NSImage imageNamed:@"right.tga"],
    //        [NSImage imageNamed:@"left.tga"],
    //        [NSImage imageNamed:@"top.tga"],
    //        [NSImage imageNamed:@"bottom.tga"],
    //        [NSImage imageNamed:@"back.tga"],
    //        [NSImage imageNamed:@"front.tga"]]];

    //-----------------------------------------------------------------------------------
    //Test 4 - try with one image

    //WORKS - set whole background to one image
    //scene.background.contents = [NSImage imageNamed:@"left.tga"];//OK

    //this proved that the image does load
    //-----------------------------------------------------------------------------------

    //use same one image in a SCNMaterialProperty
    //DOESNT WORK - so issue is the SCNMaterialProperty
    //    SCNMaterialProperty *scnMaterialProperty = [SCNMaterialProperty materialPropertyWithContents:[NSImage imageNamed:@"right.tga"]];
    //    scnMaterialProperty.intensity = 0.7;
    //    scene.background.contents = scnMaterialProperty;//OK
    //-----------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------
    //SKYBOX WORKS!!!!
    //-----------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------

    //version3 - pass array in directly (NOT through SCNMaterialProperty!!!!)
    scene.background.contents = @[[NSImage imageNamed:@"right.tga"],
                                  [NSImage imageNamed:@"left.tga"],
                                  [NSImage imageNamed:@"top.tga"],
                                  [NSImage imageNamed:@"bottom.tga"],
                                  [NSImage imageNamed:@"back.tga"],
                                  [NSImage imageNamed:@"front.tga"]];

    //-----------------------------------------------------------------------------------
    //DOESNT WORK
    //scene.background.contents = @"frozen.mov";//

    //-----------------------------------------------------------------------------------
    //CAMERA and CUBE
    //-----------------------------------------------------------------------------------
    // create and add a camera to the scene
    SCNNode *cameraNode = [SCNNode node];
    cameraNode.camera = [SCNCamera camera];
    [scene.rootNode addChildNode:cameraNode];

    // place the camera
    cameraNode.position = SCNVector3Make(0, 0, 2);

    // create and add a 3d box to the scene
    SCNNode *boxNode = [SCNNode node];
    boxNode.geometry = [SCNBox boxWithWidth:1 height:1 length:1 chamferRadius:0.02];
    [scene.rootNode addChildNode:boxNode];
    //-----------------------------------------------------------------------------------

    // create and configure a material
//    SCNMaterial *material = [SCNMaterial material];
//    material.diffuse.contents = [NSColor brownColor];//= [NSImage imageNamed:@"texture"];
//    material.specular.contents = [NSColor brownColor];
//    material.specular.intensity = 0.2;
//    material.locksAmbientWithDiffuse = YES;
//    

//    //material.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];
//    material.reflective.contents = @[@"right.png", @"left.png", @"top.png", @"bottom.png", @"back.png", @"front.png"];
//    
//    material.diffuse.contents = [NSColor blackColor];
//    
//    
//    // set the material to the 3d object geometry
//    boxNode.geometry.firstMaterial = material;
//    
//    earth-reflective.jpg
//    boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
//    

    //boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"earth-reflective"];
//    boxNode.geometry.firstMaterial.reflective.contents = @[@"right.tga", @"left.tga", @"top.tga", @"bottom.tga", @"back.tga", @"front.tga"];



    //-----------------------------------------------------------------------------------
    //CUBE MATERIAL
    //-----------------------------------------------------------------------------------

    //make the cube reflect the sky
    //the sky isnt really being reflected comment out line above "scene.background.contents = ...."
    //and cube will still reflect the sky
    //also comment out both of these lines "boxNode.geometry.firstMaterial.reflective
    //and sky box will still work
    //-----------------------------------------------------------------------------------

    //VERSION 1 - ALSO WORKS!
    boxNode.geometry.firstMaterial.reflective.contents = @[[NSImage imageNamed:@"right.tga"],
                                                           [NSImage imageNamed:@"left.tga"],
                                                           [NSImage imageNamed:@"top.tga"],
                                                           [NSImage imageNamed:@"bottom.tga"],
                                                           [NSImage imageNamed:@"back.tga"],
                                                           [NSImage imageNamed:@"front.tga"]];

    boxNode.geometry.firstMaterial.reflective.intensity = 0.7;
    //-----------------------------------------------------------------------------------
    //VERSION 2 - ALSO WORKS!
    //this uses same image for all sides of the cube
    //boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"right.tga"];//ok
    //boxNode.geometry.firstMaterial.reflective.intensity = 0.7;


    //-----------------------------------------------------------------------------------
    //VERSION 3 - BLACK 2010 a space odyssey shiny cube
    //get the earth-reflective.jpg from
    //https://developer.apple.com/library/mac/samplecode/SceneKit_Slides_WWDC2013/Introduction/Intro.html
//    boxNode.geometry.firstMaterial.reflective.contents = [NSImage imageNamed:@"earth-reflective"];
//    boxNode.geometry.firstMaterial.reflective.intensity = 0.7;

    //-----------------------------------------------------------------------------------
    //-----------------------------------------------------------------------------------
    //REQUIRED else above reflections look weird
    boxNode.geometry.firstMaterial.diffuse.contents = [NSColor blackColor];
    boxNode.geometry.firstMaterial.specular.intensity = 0.0;

    //-----------------------------------------------------------------------------------
    // animate the 3d object - camera control is on so cube spins with the sky
    //comment in to animate cube

//    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"rotation"];
//    animation.toValue = [NSValue valueWithSCNVector4:SCNVector4Make(1, 1, 0, M_PI*2)];
//    animation.duration = 5;
//    animation.repeatCount = MAXFLOAT; //repeat forever
//    [boxNode addAnimation:animation forKey:nil];

    // set the scene to the view
    self.scene = scene;

    // allows the user to manipulate the camera
    self.allowsCameraControl = YES;

    // show statistics such as fps and timing information
    self.showsStatistics = YES;

}
@end

答案 2 :(得分:0)

Swift 5.0 / iOS 13

较新的Swift版本中的一些更改:

    // Be aware, that the order of the images is relevant, not the names, and
    // "BACK" means the background at the most negativ value of z-dimension
    // (exactly where the standard camera looks at, so you could probably think its "front")

    background.contents = [UIImage(named: "Right"),
                           UIImage(named: "Left"),
                           UIImage(named: "Top"),
                           UIImage(named: "Bottom"),
                           UIImage(named: "Back"),
                           UIImage(named: "Front")]

答案 3 :(得分:0)

这是对我有用的顺序:

background.contents = [UIImage(named: "Right"),
                       UIImage(named: "Left"),
                       UIImage(named: "Top"),
                       UIImage(named: "Bottom"),
                       UIImage(named: "Front"),
                       UIImage(named: "Back")]

几乎一样,只是交换最后两个。