Reputation: 2897
I've created a simple project to try out SceneKit, added a scene which contains a man character and a camera.
The problem is the code behaves differently on the simulator and on the device.
When loading the man character into a SCNNode object, in the simulator this "man" node has child nodes, which themselves contain geometry.
However when running on device, the man node contains no child nodes and itself have the geometry.
Why is that so? Can someone explain what exactly I messed up?
I've uploaded the sample project to GitHub so you could check it out and run it on your simulator and device.
https://github.com/iamBlueGene/SceneKitExperiment
Thanks, Eli.
Upvotes: 2
Views: 279
Reputation: 1373
I encountered the same issue. The code worked on the simulator and within a macOS app, but it didn't work on a real iPhone device.
This is because the simulator and macOS have all the necessary permissions to access the file, whereas on iOS, we need to explicitly specify that we want to access the resource file.
This can be achieved by guarding the result of the following function:
guard url.startAccessingSecurityScopedResource() else {
return
}
Upvotes: 0
Reputation: 428
I think I've figured this one out.
The problem is that because the vertexs are split across the containers in the .dae file is due to limitations on the number of vertexes, different configuration can open the file differently.
You can try opening the scene again and exporting it again (or maybe just the character if you can) and check again.
Upvotes: 1
Reputation: 2897
I added the following method to your ViewController.m
just to see what was going on.
- (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;
}
}
And received the following output when running on both the simulator and device (when passing a reference to the man node).
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
. . .
This seems to line up with what you saw when running on the the device. Looking in both the XCode scene editor and Blender showed that there were several components that were apparently being merged.
There are some options you can specify when importing a scene. The default is documented as not flattening the scene (as we observe is happening), but just to confirm I tried the following. This produced the same output as above.
NSDictionary* sceneLoadOpts = [NSDictionary dictionaryWithObjectsAndKeys:
SCNSceneSourceFlattenSceneKey, [NSNumber numberWithBool:NO],
nil];
SCNScene *characterScene = [SCNScene sceneNamed:@"character-male-muscle.dae"
inDirectory:nil
options:sceneLoadOpts];
The device (or simulator for that matter) doesn't load the .dae
file directly. This is compiled by the scntool
into a c3d file. I converted the dae to a c3d file, then back to a dae and found the different components remained. The flattening was not a result of this compression process.
Finally I loaded the model in Blender and rearranged the model tree so that all the geometry nodes were at the same level as the parent node. This indeed resulted in multiple geometry components on both the simulator and device, but that's probably going a little far...
The vertex counts (65535) and names of these components ("splitContainerX") seem to indicate they are only separate geometry components due to constraints on vertex indexing (2^16). In short, I don't think you really want to treat this model as separate components anyway. Current theory is that there's a flag somewhere in the dae file that states these components should be merged when possible.
Upvotes: 0