我正在尝试学习SceneKit的方法,作为一个例子,我想我会尝试使用SDK构建一个太阳系。我能够添加SCNode对象并配置其材质属性,如图案和光照。此外,我能够旋转行星,但我似乎无法理解如何沿着特定的路径“旋转”它们。
到目前为止我的代码看起来像:
// 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;
我在AppleDocs的某个地方读到你需要在Sun的坐标系中添加行星,而不是在根节点中添加行星但是我不确定我是否理解这一点。
让我知道你是如何做到的。
答案 0 :(得分:14)
SceneKit不提供动态路径API。但是,有几种方法可以设置像太阳系这样的东西。
见过orrery?这是SCNNode文档中所说的模型;它也是WWDC presentation在"场景图摘要"上所做的事情。滑动。诀窍在于你使用一个节点来表示行星围绕太阳旋转的参考框架 - 就像将行星固定在一个orrery中的电枢,如果你使这个节点绕其中心轴旋转,任何一个孩子您附加到它的节点将遵循循环路径。相关代码位于该示例代码项目中的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];
您无法制作遵循您在3D空间中建模的特定路径的动画,但您可以创建一个在3D空间中的多个位置之间插值的关键帧动画。下面的(未经测试的)代码在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"];
使用物理! SCNPhysicsField
类模拟径向引力,因此您可以将重力场放入场景中,为行星添加一些物理体,然后坐下来观察您的太阳系<罢工>灾难性地摧毁自己来到生活!在这里获得真实的行为需要大量的试验和错误 - 你需要为每个行星设置与你预期的轨道相切的初始速度,并调整速度以使其正确。研究太阳系的一些星历数据可能会有所帮助。