以编程方式更改 SCNScene 的 sceneNamed

Change SCNScene's sceneNamed programmatically

我正在尝试用代码更改当前 sceneNamed,但我的方法似乎有一些问题。首先,新的场景会改变,但我必须触摸或评价对象以改变过程happens.Second,似乎childNodeWithName根本没有改变!这是我的代码:

    - (void)load3DObjectName:(NSString*)name nodeName:(NSString*)nodeName zPhone:(CGFloat)positioniPhone zPad:(CGFloat)positioniPad{

        SCNScene * scene = [SCNScene sceneNamed:name];
        // retrieve the ship node
        SCNNode *trex = [scene.rootNode childNodeWithName:nodeName recursively:YES];


        if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {

             trex.position = SCNVector3Make(0, 0, positioniPhone);

        } else {

             trex.position = SCNVector3Make(0, 0, positioniPad);
        }



        _the3DScence.scene = scene;
        _the3DScence.autoenablesDefaultLighting = YES;
        _the3DScence.allowsCameraControl = YES;
        _the3DScence.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:1.00];
    }



// Load default object :

- (void)viewDidLoad {

    [self load3DObjectName:@"cube.dae" nodeName:@"cube1" zPhone:-40 zPad:-30];

}

//Trying to change the 3D object with button:
- (IBAction)nextObject:(id)sender {

    [self load3DObjectName:@"redCube.dae" nodeName:@"cube2" zPhone:-40 zPad:-30];

}

- (IBAction)changeIt:(id)sender {

     [self load3DObjectName:@"dayere.dae" nodeName:@"Sphere" zPhone:-40 zPad:-40];
}

这是源代码: https://www.dropbox.com/s/rrvbxmrb9wcrnoj/3D%20Objects%20Change.zip?dl=0

Dropbox 版本中的代码不是我上面发布的。这是 Dropbox 版本:

-(无效)viewDidLoad {
    [超级viewDidLoad];
    // 在加载视图后做任何额外的设置,通常是从 nib。

    [自加载3DObjectName:@"cube.dae" nodeName:@"Cube" zPhone:-40 zPad:-40];
}

- (void)didReceiveMemoryWarning {
    [超级 didReceiveMemoryWarning];
    // 处理任何可以重新创建的资源。
}

- (void)load3DObjectName:(NSString*)name nodeName:(NSString*)nodeName zPhone:(CGFloat)positioniPhone zPad:(CGFloat)positioniPad{
    SCNScene * scene = [SCNScene sceneNamed:name];
    // 检索船舶节点
    SCNNode *node = [scene.rootNode childNodeWithName:nodeName recursively:YES];

    如果 ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
        node.position = SCNVector3Make(0, 0, positioniPhone);
    }
    别的 {
        node.position = SCNVector3Make(0, 0, positioniPad);
    }
    _the3DView.scene = 场景;
    _the3DView.autoenablesDefaultLighting = 是;
    _the3DView.allowsCameraControl = 是;
    _the3DView.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:1.00];
}

- (IBAction)changeIt:(id)发件人{
     [自加载3DObjectName:@"dayere.dae" nodeName:@"Sphere" zPhone:-40 zPad:-40];
}

在我看来,您的第二轮代码运行良好。我注意到您在 Dropbox 示例中加载的 scenes/nodes 与您首先发布的代码中加载的不同。所以这让我觉得您的 DAE 文件中有些东西不是您期望的那样。检查丢失或拼写错误的节点名称。在 childNodeWithName:sceneNamed: 调用之后添加 NSAssert 调用,以确保您确实成功加载了场景并找到了子节点。

SCNScene * scene = [SCNScene sceneNamed:name];
NSAssert(scene, @"failed to load scene named %@", name);
// retrieve the ship node
SCNNode *node = [scene.rootNode childNodeWithName:nodeName recursively:YES];
NSAssert(node, @"couldn't fine child node named %@", nodeName);

如果 NSAsserts 失败,请使用 3D 编辑工具修复 Collada 文件。

另请注意,当您替换 the3DView.scene 时(另外:请不要直接修改实例变量,而是使用访问器方法!),您也在替换相机和照明。所以你应该预料到相机定位会出现抖动。也许你想制作动画?或者对象的 remove/replace 个节点,不影响相机和照明?

当我 运行 将您发布到 Dropbox 的代码时,我看到满屏都是红色。当我缩小并旋转相机时,它看起来像这样:

点击 "Button" 按钮后,我看到了这个:

所以我看过你的项目。问题是:你的场景中没有相机。所以我将每个场景的相机手动放置在相同的距离,并根据需要移动节点。这是现在的样子:

- (void)load3DObjectName:(NSString*)name nodeName:(NSString*)nodeName zPhone:(CGFloat)positioniPhone zPad:(CGFloat)positioniPad
{
SCNScene * scene = [SCNScene sceneNamed:name];
SCNNode *node = [scene.rootNode childNodeWithName:nodeName recursively:YES];

if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
    node.position = SCNVector3Make(0, 0, positioniPhone);

} else {

    node.position = SCNVector3Make(0, 0, positioniPad);
}

SCNCamera *cam = [[SCNCamera alloc] init];
cam.xFov = 35;
cam.yFov = 35;
cam.zFar = 5000;
cam.zNear = 0;
SCNNode *camNode = [[SCNNode alloc] init];
camNode.camera = cam;

camNode.position = SCNVector3Make(0, 0, 400);

[scene.rootNode addChildNode:camNode];

_the3DView.pointOfView = camNode;

_the3DView.scene = scene;
_the3DView.autoenablesDefaultLighting = YES;
_the3DView.allowsCameraControl = YES;
_the3DView.backgroundColor = [UIColor colorWithRed:0.92 green:0.92 blue:0.92 alpha:1.00];
}

我还更改了您的对象位置以进行测试:

- (IBAction)changeIt:(id)sender
{
 [self load3DObjectName:@"dayere.dae" nodeName:@"Sphere" zPhone:-340 zPad:-340];
}

还有这个:

- (void)viewDidLoad
{
   [super viewDidLoad];
   [self load3DObjectName:@"cube.dae" nodeName:@"Cube" zPhone:-40 zPad:-40];
}

最后但同样重要的是,屏幕截图: