使用 SceneKit 在 3D 空间中旋转 SCNode 对象 [英] Revolve a SCNode object in the 3D Space using SceneKit

查看:41
本文介绍了使用 SceneKit 在 3D 空间中旋转 SCNode 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习如何使用 SceneKit,例如,我想我会尝试使用 SDK 构建一个太阳系.我能够添加 SCNode 对象并配置其材质属性,例如图案和照明.此外,我能够旋转行星,但我似乎无法理解如何沿着特定路径旋转"它们.

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. I am able to add SCNode objects and configure its material properties like pattern and lighting. 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;

我在 AppleDocs 的某处读到您需要在太阳坐标系中而不是在根节点中添加行星,但我不确定我是否理解正确.

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.

让我知道你是如何开始做这件事的.

Let me know how do you get about doing this.

推荐答案

SceneKit 不提供动画路径 API.不过,有几种方法可以建立类似太阳系的东西.

SceneKit doesn't provide an animate-along-path API. There are several ways to set up something like a solar system, though.

  1. 见过orrery吗?这是SCNNode 文档正在讨论;这也是 WWDC 演示文稿 在场景图摘要"幻灯片上执行.诀窍是您使用一个节点来表示行星绕太阳公转的参考系 - 就像将行星固定在太阳镜中的电枢一样,如果您使该节点绕其中心轴旋转,则您附加到的任何子节点它将遵循圆形路径.相关代码位于该示例代码项目的 ASCSceneGraphSummary.m 中(在此处浓缩为仅显示节点层次结构设置):

  1. Ever seen an orrery? This is the model that bit in the SCNNode documentation is talking about; it's also what the WWDC presentation does on the "Scene Graph Summary" slide. 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. The relevant code for this is in ASCSceneGraphSummary.m in that sample code project (condensed to just show node hierarchy setup 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];

  • 您无法制作遵循您在 3D 空间中建模的特定路径的动画,但您可以制作在 3D 空间中的多个位置之间进行插值的关键帧动画.下面的(未经测试的)代码在 xz 平面中围绕方形移动节点...添加更多点以获得更圆的形状.

  • 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. The (untested) code below moves a node around a square shape in the xz-plane... add more points to get a rounder shape.

    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 类模拟径向重力,因此您可以将重力场放入场景中,为行星添加一些物理体,然后坐下来观看您的太阳系灾难性地自我毁灭生活!在这里获得真实的行为需要大量的反复试验——你需要为每颗行星设置一个与你期望的轨道相切的初始速度,并调整该速度以使其正确.研究我们太阳系的一些星历数据可能会有所帮助.

  • 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! 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.

    这篇关于使用 SceneKit 在 3D 空间中旋转 SCNode 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆