How to Get The Advantages of Scenekit's Level Editor Programatically

Stop sharing node's geometry with its clone programmatically

According to the clone() API reference, you can copy the geometry after cloning, this will create a new unshared geometry for your node.

let newNode = node.clone()
newNode.geometry = node.geometry?.copy() as? SCNGeometry

The material attached to the copied geometry is still the same one being used on the original, so any changes will still affect both.
Either create a new material, or make a copy.

if let newMaterial = newNode.geometry?.materials.first.copy() as? SCNMaterial {
//make changes to material
newNode.geometry?.materials = [newMaterial]
}

Workflow between blender and xcode (scenekit)

SceneKit supports materials exported in DAE from Blender. It doesn't support every possible shading option that Blender has, but unless you're doing exotic stuff it should cover most of what you're looking for.

At run time there's no difference between materials loaded from DAE and those created programmatically.

What you do want to think about at authoring/export time is stuff like real-time versus static lighting/shadows and high-poly geometry versus baked normal maps. In other words, material performance is more about how the materials are set up (complexity) than where they're set up (imported or at run time). See WWDC 2014 session 610: Building a Game with SceneKit for some tips.

How to add a 3D object as SCNNode in ARKit2?

To add .dae or .obj object to the scene, you need to get childNode of the .dae object and simply add it to your scene. I recommend to convert your .dae file to .scn simply using Xcode's Editor menu.

You also need the node's name, which can be accessed in Scene Graph View. Just click on your .obj file and click the Scene Graph View button on bottom left corner of the Xcode scene editor. Here, my node's name is "objectNode":

Sample Image

Now you can add the 3D object as a SCNNode to your scene:

override func viewDidLoad() {
super.viewDidLoad()
...

let objectScene = SCNScene(named: "object.scn") // Here, add your .obj or .scn file
let objectNode: SCNNode = objectScene.rootNode.childNode(withName: "YourObjectName", recursively: true) // Get the object name from Scene Graph View, which is "objectNode" for me.
objectNode.position = SCNVector3(0,0,-4)

let scene = SCNScene() // Main scene of the app
scene.rootNode.addChildNode(objectNode)
sceneView.scene = scene
...
}

How can I apply coordinates to a 3D earth model in xcode's scenekit?

You don't need to go into complex math to do this. All you need to do is add two extra helper nodes.

Lets assume the Earth is represented by earthNode with its geometry (a sphere) at the centre of the node and with a radius of 100 points.

Add a child node to it with the same centre called longtudeHandle, without any geometry.

Now add another child node to the first one latitudeHandle, without any geometry.

Then you add the space station node stationNode as a child to latitudeHandleNode, but not in the centre. Offset it along the X axis by, say, 105 points to place it 5 points above "the Equator".

SCNNode * longtudeHandle = [SCNNode node];
[earthNode addChildNode:longtudeHandle];

SCNNode * latitudeHandle = [SCNNode node];
[longtudeHandle addChildNode:latitudeHandle];

stationNode.position = SCNVector3Make(105, 0, 0);
[latitudeHandle addChildNode:stationNode];

You should end up with the following node graph in your scene

earthNode
|
|--------longitudeHandle
|
|----------latitudeHandle
|
|-----------stationNode

As a result you have 4 nested coordinate systems and every node 3D rotation is set according to its parent node coordinate system.

You can then manipulate the long/lat position of your Station using

  • longitudeHanlde.eulerAngles Y component for longitude angle in radians
  • latitudeHanlde.eulerAngles Z component for latitude angle in radians

which should look like

longitudeHandle.eulerAngles = SCNVector3Make(0, LONGITUDE, 0);
latitudeHanlde.eulerAngles = SCNVector3Make(0, 0, LATITUDE);

An additional benefit of using these nested helper nodes is that the Station will always be perpendicular to it's parent's X axis and respectively the planet surface, while if you use complex math to position it in orbit and want to achieve the same effect it becomes even more complex.


Alternatively, you should be able to do the same with only one helper (positioning) node and whichever "rotational" property you are familiar with to orient it in 3D space

.euler​Angles  // SCNVector3
.rotation // SCNVector4
.orientation // SCNQuaternion
.transform // SCNMatrix4, includes position and scale

but this will require some math and/or use of matrices or quaternions (which I've not spent time to learn yet).



Related Topics



Leave a reply



Submit