在设备上运行时没有子节点

问题描述 投票:0回答:3

我创建了一个简单的项目来尝试 SceneKit,添加了一个包含一个男人角色和一个相机的场景。

问题是代码在模拟器和设备上的行为不同。

将 man 角色加载到 SCNNode 对象中时,在模拟器中,该“man”节点具有子节点,这些子节点本身包含几何图形。

但是,当在设备上运行时,man 节点不包含子节点,并且本身具有几何结构。

为什么会这样呢?有人能解释一下我到底搞砸了什么吗?

我已将示例项目上传到 GitHub,以便您可以查看它并在模拟器和设备上运行它。

https://github.com/iamBlueGene/SceneKitExperiment

谢谢,伊莱。

ios objective-c cocoa-touch scenekit
3个回答
1
投票

我想我已经弄清楚了。

问题是,由于 .dae 文件中顶点被分割到各个容器中,这是由于顶点数量的限制,不同的配置可以以不同的方式打开文件。

您可以尝试再次打开场景并再次导出(或者如果可以的话,也可以仅导出角色)并再次检查。


0
投票

我将以下方法添加到您的

ViewController.m
只是为了看看发生了什么。

- (void)printNodeTree: (SCNNode*)node levelIndent:(NSString*) indent{

    if (node != nil) {
        BOOL hasGeom = node.geometry == nil;
        NSString *nodeName = [NSString stringWithFormat:@"%@%@", indent, node.name];
        NSString *geomStr = [NSString stringWithFormat:@"%@ has geometry: %@", indent, hasGeom ? @"YES" : @"NO"];
        printf("%s \n", [nodeName UTF8String]);
        printf("%s \n", [geomStr UTF8String]);

        for (id childNode in [node childNodes]) {
            [self printNodeTree:childNode levelIndent:[NSString stringWithFormat:@"%@   ",indent]];
        }
    } else {
        return;
    }
}

并且在模拟器和设备上运行时收到以下输出(将引用传递给 man 节点时)。

Model_1 
 has geometry: YES 
   Model_1-splitContainer 
    has geometry: YES 
      Model_1-splitContainer-split0 
       has geometry: NO 
      Model_1-splitContainer-split1 
       has geometry: NO 
      Model_1-splitContainer-split2 
       has geometry: NO 
      Model_1-splitContainer-split3 
       has geometry: NO 
      . . .

这似乎与您在设备上运行时看到的一致。查看 XCode 场景编辑器和 Blender 发现有几个组件显然正在合并。

导入场景时可以指定一些选项。默认情况被记录为不会展平场景(正如我们观察到的那样),但只是为了确认我尝试了以下操作。这产生了与上面相同的输出。

NSDictionary* sceneLoadOpts = [NSDictionary dictionaryWithObjectsAndKeys:
    SCNSceneSourceFlattenSceneKey, [NSNumber numberWithBool:NO],
    nil];

SCNScene *characterScene = [SCNScene sceneNamed:@"character-male-muscle.dae"
    inDirectory:nil 
    options:sceneLoadOpts];

设备(或模拟器)不会直接加载

.dae
文件。这是由
scntool
编译成c3d文件的。我将 dae 转换为 c3d 文件,然后又转换回 dae,发现仍然存在不同的组件。扁平化并不是压缩过程的结果。

最后我在 Blender 中加载模型并重新排列模型树,使所有几何节点与父节点处于同一级别。这确实导致了模拟器和设备上都有多个几何组件,但这可能有点远了......

顶点计数(65535)和这些组件的名称(“splitContainerX”)似乎表明由于顶点索引(2^16)的限制,它们只是单独的几何组件。简而言之,我不认为您真的想将此模型视为单独的组件。目前的理论是,dae 文件中的某处有一个标志,表明这些组件应在可能的情况下合并。


0
投票

我遇到了同样的问题。该代码可以在模拟器和 macOS 应用程序中运行,但不能在真正的 iPhone 设备上运行。

这是因为模拟器和 macOS 拥有访问该文件的所有必要权限,而在 iOS 上,我们需要明确指定要访问资源文件。

这可以通过保护以下函数的结果来实现:

guard url.startAccessingSecurityScopedResource() else {
    return
}
© www.soinside.com 2019 - 2024. All rights reserved.