Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am new to this. And there comes my first problem.

I build an object loader with SceneKit. I got the path, the Object is available, but I have no clue how I can color the shown object.

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

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

This didn't work. I also tried with:

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

Or:

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

Nothing works. When I start the app, every object is displayed. So far the OBJ-Loader works out very well. But everything is still gray. I totally have no clue how to color the displayed objects. Has anyone a hint/idea/solution for me?

Btw. I want to avoid that I have to build a geometry out of the OBJ-Informations manually. So I try to solve this by the SCNScene.

like image 454
Alexander Langer Avatar asked Jan 06 '23 15:01

Alexander Langer


1 Answers

The major problem was that the import by a SCNScenedoes not work that way. So the right solution is to import the obj.file into a SCNNode, add a SCNMaterial with the chosen color (or an image) to the SCNNode and give the SCNNodeto the SCNScene. To load the obj.file, you need to import that by Model IO Framework.

I will give some code how I made it colorful.

#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];

Alternately you can add a color by this:

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

Now you can import any obj.file externally (from any chosen folder you like) and color it.

Thanks to SGlindemann, cashmash and Hal Mueller, who helped out to find that solution.


UPDATE (29.1.2017)

Somehow the way above does not work anymore. I did not figure out yet what changed. But I made another code that makes loading for 3D files possible (from mainBundle, not externally). Here I start from a SCNNode class which is called by the ViewController.m. The SCNScene is setup in the ViewController. Following there is the code which I wrote for the SCNNode class.

Before you start, put the .obj and .mtl file (both with same name) into your Xcode project. You don't need to convert it to a scene.

#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;

This returned self has to be added into your view.

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

The MDLAssetloads the .obj-file with the corresponding .mtl-file and png-File. I used this code to load objects from MagicaVoxel (this exports obj+mtl+png at once). I did not get deep into it yet.

I did NOT try this code with external loadings or typing in colors manually via SCNMaterial. So there is no statement whether this works or not. I did not try.

like image 69
Alexander Langer Avatar answered Jan 18 '23 10:01

Alexander Langer