简体   繁体   English

使用SceneKit在3D空间中旋转SCNode对象

[英]Revolve a SCNode object in the 3D Space using SceneKit

I am trying to learn my way around SceneKit and as an example, I thought I'd try to build a solar system using the SDK. 我试图在SceneKit周围学习,作为一个例子,我想我会尝试使用SDK构建一个太阳能系统。 I am able to add SCNode objects and configure its material properties like pattern and lighting. 我能够添加SCNode对象并配置其材质属性,如图案和光照。 Also, I am able to rotate the planets, but I can't seem to understand how do I "revolve" them along a particular path. 此外,我能够旋转行星,但我似乎无法理解如何沿着特定的路径“旋转”它们。

My code so far looks like: 到目前为止我的代码看起来像:

// 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 in the Sun's co-ordinate system and not in the root node but I am not sure if I understood that properly anyway. 我在AppleDocs的某个地方读到你需要在Sun的坐标系中添加行星,而不是在根节点中添加行星,但我不确定我是否理解这一点。

Let me know how do you get about doing this. 让我知道你是如何做到这一点的。

SceneKit doesn't provide an animate-along-path API. SceneKit不提供动态路径API。 There are several ways to set up something like a solar system, though. 但是,有几种方法可以设置像太阳系这样的东西。

  1. Ever seen an orrery ? 曾经见过一个orrery This is the model that bit in the SCNNode documentation is talking about; 这是SCNNode文档中的位所讨论的模型; it's also what the WWDC presentation does on the "Scene Graph Summary" slide. 这也是WWDC演示文稿在“场景图摘要”幻灯片上的作用。 The trick is that you use one node to represent the frame of reference for a planet's revolution around the sun — like the armature that holds a planet in an orrery, if you make this node rotate around its central axis, any child node you attach to it will follow a circular path. 诀窍在于,您使用一个节点来表示行星围绕太阳旋转的参考框架 - 就像将行星固定在一个orrery中的电枢,如果您使该节点围绕其中心轴旋转,您附加的任何子节点它将遵循循环路径。 The relevant code for this is in ASCSceneGraphSummary.m in that sample code project (condensed to just show node hierarchy setup here): 相关代码在该示例代码项目中的ASCSceneGraphSummary.m中(精简到此处仅显示节点层次结构设置):

     // 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]; 
  2. You can't make an animation that follows a specific path you model in 3D space, but you could make a keyframe animation that interpolates between several positions in 3D space. 您无法制作遵循在3D空间中建模的特定路径的动画,但您可以制作在3D空间中的多个位置之间插值的关键帧动画。 The (untested) code below moves a node around a square shape in the xz-plane... add more points to get a rounder shape. 下面的(未经测试的)代码在xz平面中围绕方形形状移动节点...添加更多点以获得更圆的形状。

     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"]; 
  3. Use physics! 使用物理! The SCNPhysicsField class models radial gravity, so you can just drop a gravity field into a scene, add some physics bodies for planets, and sit back and watch your solar system cataclysmically destroy itself come to life! SCNPhysicsField类模拟径向重力,因此您可以将重力场放入场景中,为行星添加一些物理体,然后坐下来观看您的太阳系 灾难性破坏自身的 生命! Getting realistic behavior here takes a lot of trial and error — you'll need to set an initial velocity for each planet tangential to what you expect its orbit to be, and tweak that velocity to get it right. 在这里获得真实的行为需要大量的试验和错误 - 你需要为每个行星设置一个与你预期的轨道相切的初始速度,并调整速度以使其正确。 Researching some ephemeris data for our solar system might help. 研究太阳系的一些星历数据可能会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM