Rotating a SCNode in 3D Space with SceneKit

I am trying to master SceneKit and as an example, I thought I would try to build a solar system using the SDK. I can add SCNode objects and adjust its material properties, such as pattern and lighting. In addition, I can rotate the planets, but I cannot understand how I can “rotate” them in a certain way.

My code looks like this:

// create a new scene SCNScene *scene = [SCNScene scene]; // create and add a camera to the scene SCNNode *cameraNode = [SCNNode node]; cameraNode.camera = [SCNCamera camera]; [scene.rootNode addChildNode:cameraNode]; // place the camera cameraNode.position = SCNVector3Make(0, 0, 2); // create and add a 3d sphere - sun to the scene SCNNode *sphereNode = [SCNNode node]; sphereNode.geometry = [SCNSphere sphereWithRadius:0.3]; [scene.rootNode addChildNode:sphereNode]; // create and configure a material SCNMaterial *material = [SCNMaterial material]; material.diffuse.contents = [NSImage imageNamed:@"SunTexture"]; material.specular.contents = [NSColor whiteColor]; material.specular.intensity = 0.2; material.locksAmbientWithDiffuse = YES; // set the material to the 3d object geometry sphereNode.geometry.firstMaterial = material; // create and add a 3d sphere - earth to the scene SCNNode *earthNode = [SCNNode node]; earthNode.geometry = [SCNSphere sphereWithRadius:0.15]; NSLog(@"Sun position = %f, %f, %f", sphereNode.position.x, sphereNode.position.y, sphereNode.position.z); earthNode.position = SCNVector3Make(0.7, 0.7, 0.7); NSLog(@"Earth position = %f, %f, %f", earthNode.position.x, earthNode.position.y, earthNode.position.z); //earthNode.physicsBody = [SCNPhysicsBody dynamicBody]; [scene.rootNode addChildNode:earthNode]; SCNMaterial *earthMaterial = [SCNMaterial material]; earthMaterial.diffuse.contents = [NSImage imageNamed:@"EarthTexture"]; earthNode.geometry.firstMaterial = earthMaterial; 

I read somewhere in AppleDocs that you need to add planets to the coordinate system of the Sun, and not to the root directory of the node, but I'm not sure if I understood this correctly.

Let me know how you do it.

+6
source share
1 answer

SceneKit does not provide an animation API along the way. However, there are several ways to create something like a solar system.

  • Ever seen orrery ? This is the model referred to in the SCNNode documentation; this is also what the WWDC presentation does on the "Scene Graphics" slide. The trick is that you use one node to represent the frame of reference for the planet to rotate around the Sun - like an armature that holds the planet in orrery, if you make this node rotate around its central axis, any child node that you attach to it will follow a circular path. The appropriate code for this is in ASCSceneGraphSummary.m in this code code project (configured to just show the hierarchical node hierarchy here):

     // Sun _sunNode = [SCNNode node]; _sunNode.position = SCNVector3Make(0, 30, 0); [self.contentNode addChildNode:_sunNode]; // Earth-rotation (center of rotation of the Earth around the Sun) SCNNode *earthRotationNode = [SCNNode node]; [_sunNode addChildNode:earthRotationNode]; // Earth-group (will contain the Earth, and the Moon) _earthGroupNode = [SCNNode node]; _earthGroupNode.position = SCNVector3Make(15, 0, 0); [earthRotationNode addChildNode:_earthGroupNode]; // Earth _earthNode = [_wireframeBoxNode copy]; _earthNode.position = SCNVector3Make(0, 0, 0); [_earthGroupNode addChildNode:_earthNode]; // Moon-rotation (center of rotation of the Moon around the Earth) SCNNode *moonRotationNode = [SCNNode node]; [_earthGroupNode addChildNode:moonRotationNode]; // Moon _moonNode = [_wireframeBoxNode copy]; _moonNode.position = SCNVector3Make(5, 0, 0); [moonRotationNode addChildNode:_moonNode]; 
  • You cannot make an animation that follows the pattern you define in 3D space, but you can make a keyframe animation that interpolates between multiple positions in 3D space. The following (unverified) code moves a node around a square shape in the xz plane ... add more points to get the shape of a circle.

     CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPaths:@"position"]; anim.values = @[ [NSValue valueWithSCNVector3:SCNVector3Make(0, 0, 1)], [NSValue valueWithSCNVector3:SCNVector3Make(1, 0, 0)], [NSValue valueWithSCNVector3:SCNVector3Make(0, 0, -1)], [NSValue valueWithSCNVector3:SCNVector3Make(-1, 0, 0)], ]; [node addAnimation:anim forKey:"orbit"]; 
  • Use physics! The SCNPhysicsField class models radial gravity, so you can simply drop the gravitational field into the scene, add some physical bodies to the planets and sit back and watch your solar system cataclysmically destroy itself comes to life! Getting realistic behavior here requires a lot of trial and error - you will need to set the initial speed for each planet, tangential to what you expect from its orbit, and adjust this speed to get it right. Researching some ephemeris data for our solar system may help.

+12
source

Source: https://habr.com/ru/post/971086/


All Articles