Objective-C Scenekit:从外部导入 OBJ 文件并为其着色

Objective-C Scenekit: Import OBJ-File externally and color it

我是新手。我的第一个问题来了。

我用 SceneKit 构建了一个对象加载器。我得到了路径,对象可用,但我不知道如何为显示的对象着色。

ScnScene *testScene = [SCNScene sceneWithURL:url options:nil error:NULL];
testScene.background.contents = [UIImage imageWithName:@"color.png"];

[self.mainView.scene.rootnode addChildNode:testScene.rootNode];

这没有用。我也试过:

SCNMaterialProperty *testColor = [SCNMaterialProperty materialPropertyWithContents [UIImage imageNamed:@"color.png"]];
testScene.rootnode.geometry.materials = testcolor;

或:

SCNMaterial *testColor = [SCNMaterial material];
testColor.diffuse.contesnts = [UIColor redColor];
testScene.rootnode.geometry.firstMaterial = testColor;

没有任何效果。当我启动应用程序时,会显示每个对象。到目前为止,OBJ-Loader 运行良好。但一切仍然是灰色的。我完全不知道如何为显示的对象着色。有人 hint/idea/solution 给我吗?

顺便说一句。我想避免必须手动从 OBJ 信息构建几何体。所以我尝试通过SCNScene解决这个问题。

您的第一个示例将设置场景的背景,但不对您的对象执行任何操作。

你的第二个例子应该给你一些编译器警告。您正在将单个 SCNMaterialProperty 分配给 testScene.rootnode.geometry.materials,它需要一个 SCNMaterial 的数组(而不是 SCNMaterialProperty)。那是你的真实代码吗?

最后一个示例根本不应该编译:您将 contents 拼错为 contesnts。除此之外,它应该可以工作。

请注意,MDLAsset 可以导入 OBJ 文件,return 可以导入 SCNNode。参见 。如果该对象是您将随项目一起运送的资产,请将其另存为 SCNScene(紧凑且经过优化),然后运送,而不是原始 OBJ。

主要问题是 SCNScene 的导入无法正常工作。所以正确的解决方案是将 obj.file 导入 SCNNode,将具有所选颜色(或图像)的 SCNMaterial 添加到 SCNNode 并给出 SCNNodeSCNScene。要加载 obj.file,您需要通过 Model IO Framework 导入它。

我会给出一些代码是如何让它变得多彩的。

#import <SceneKit/SceneKit.h>
#import <ModelIO/ModelIO.h>
#import <SceneKit/ModelIO.h>

...

@property (nonatomic) SCNView* mainView;

.....

MDLAsset *asset = [[MDLAsset alloc] initWithURL:url];     
SCNScene *scene = [SCNScene scene];
SCNNode *node = [SCNNode nodeWithMDLObject:[asset objectAtIndex:0]];

SCNMaterial *material = [SCNMaterial material];
material.diffuse.contents = [UIColor colorWithHue:0 saturation:0.1 brightness:0.5 alpha:1];
node.geometry.firstMaterial = material;

[scene.rootNode addChildNode:node];
[self.mainView.scene.rootNode addChildNode:scene.rootNode];

或者您可以通过以下方式添加颜色:

material.diffuse.contents = [UIImage imageNamed:@"farbe.png"];

现在您可以从外部(从您喜欢的任何选定文件夹)导入任何 obj.file 并为其着色。

感谢 SGlindemann、cashmash 和 Hal Mueller,他们帮助找到了该解决方案。


更新 (29.1.2017)

不知何故,上面的方法不再起作用了。我还没有弄清楚发生了什么变化。但是我编写了另一个代码,使 3D 文件的加载成为可能(来自 mainBundle,而不是外部)。这里我从 SCNNode class 开始,它被 ViewController.m 调用。 SCNScene 设置在 ViewController 中。下面是我为 SCNNode class.

编写的代码

开始之前,将 .obj 和 .mtl 文件(两者同名)放入您的 Xcode 项目中。您无需将其转换为场景。

#import <ModelIO/ModelIO.h>
#import <SceneKit/ModelIO.h>

...

@property (nonatomic) SCNNode *objectNode;

...

NSString* path = [[NSBundle mainBundle]
            pathForResource:[NSString stringWithFormat:@"name of the obj.file"]
            ofType:@"obj"];
NSURL *url = [NSURL fileURLWithPath:path];
MDLAsset *asset = [[MDLAsset alloc]initWithURL:url];

// Create the Block
self.objectNode = [SCNNode nodeWithMDLObject:[asset objectAtIndex:0]];


[self addChildNode: self.objectNode];

return self;

返回的 self 必须添加到您的视图中。

[self.view.scene.rootNode addChildNode:returnedObj];

MDLAsset加载 .obj 文件以及相应的 .mtl 文件和 png 文件。我使用这段代码从 MagicaVoxel 加载对象(这一次导出 obj+mtl+png)。我还没有深入。

我没有尝试使用外部加载或通过 SCNMaterial 手动输入颜色的代码。所以没有声明这是否有效。我没试过。