[英]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.
但是,有几种方法可以设置像太阳系这样的东西。
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];
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"];
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.