帮酷LOGO
  • 显示原文与译文双语对照的内容
文章标签:控制  Space  spa  CORE  
Gyroscope Driven Drawing in 3D Space

  • 源代码名称:SwiftSpace
  • 源代码网址:http://www.github.com/FlexMonkey/SwiftSpace
  • SwiftSpace源代码文档
  • SwiftSpace源代码下载
  • Git URL:
    git://www.github.com/FlexMonkey/SwiftSpace.git
  • Git Clone代码到本地:
    git clone http://www.github.com/FlexMonkey/SwiftSpace
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/FlexMonkey/SwiftSpace
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
  • SwiftSpace

    3D 空间的陀螺仪驱动图

    辅助项目:http://flexmonkey.blogspot.co.uk/2015/08/coremotion-controlled-3d-sketching-on.html

    我最近在创作应用程序中看到的InkScape演示让我印象深刻。 InkScape是一个允许用户在 3D 空间中绘制的Android 应用,它是由设备的加速度计控制的。 它是由a 激发的,前期加速度加速度计,使用轨迹轨道。

    当然我的第一个想法是"我如何在Swift中做到这一点"。 我以前从未与CoreMotion做过任何工作,所以这是学习一些新东西的好机会。 我的第一个呼叫端口是关于NSHipster的iOS运动的优秀文章。

    我的应用程序的计划是使用一个运动控制摄像头在SceneKit世界中心的偏移 pivot 点旋转一个 SceneKit 。 在 each touchesBegan我在屏幕中央创建一个新的平面框,然后在 touchesMoved ( ),我使用触摸位置附加到新创建的几何图形的漫射材质。

    简单我们把它分解一下: !

    正在创建照相机

    我希望摄像机总是在世界中心转动,然后转动到世界中心。 要帮助这两个方面,相机属性的pivot 和使用"查看约束"。 首先,我创建一个 node 来代表世界的中心和相机本身:

    let centreNode =SCNNode()
     centreNode.position=SCNVector3(x: 0, y: 0, z: 0)
     scene.rootNode.addChildNode(centreNode)
     let camera =SCNCamera()
     camera.xFov=20 camera.yFov=20

    接下来,SCNLookAtConstraint意味着我翻译相机,它将始终指向中心:

    let constraint =SCNLookAtConstraint(target: centreNode)
     cameraNode.constraints= [constraint]

    "。"。最后,设置相机的pivot 将重新定位它,但是让它绕世界中心旋转:

     cameraNode.pivot=SCNMatrix4MakeTranslation(0, 0, -cameraDistance)

    处理iPhone运动

    接下来是处理iphone的运动以旋转相机。 记住iphone的滚动是沿着front-to-back轴旋转而且它的音调是沿它的side-to-side轴旋转的:

    。我将使用这些特性来控制我的摄影机和y 轴角度。

    第一步是创建一个CMMotionManager实例并确保它是可以用的和工作的( 所以这个代码不能在模拟器上工作):

    let motionManager =CMMotionManager()
     guard motionManager.gyroAvailableelse {
     fatalError("CMMotionManager not available.")
     }

    接下来,使用一个小的block 代码启动运动管理器,每次更新都调用一个。 我使用元组存储iPhone的初始姿态,简单地使用初始值和当前姿态的差异来设置相机角度:

    let queue = NSOperationQueue.mainQueue motionManager.deviceMotionUpdateInterval=1/30 motionManager.startDeviceMotionUpdatesToQueue(queue())
     {
     (deviceMotionData: CMDeviceMotion?, error: NSError?) iniflet deviceMotionData = deviceMotionData
     {
     if (self.initialAttitude==nil)
     {
     self.initialAttitude= (deviceMotionData.attitude.roll,
     deviceMotionData.attitude.pitch)
     }
     self.cameraNode.eulerAngles.y=Float(self.initialAttitude!.roll- deviceMotionData.attitude.roll)
     self.cameraNode.eulerAngles.x=Float(self.initialAttitude!.pitch- deviceMotionData.attitude.pitch)
     }
     }

    3中的##Drawing

    因为我知道相机的角度,所以用 touchesBegan() 方法把目标几何图对齐非常简单- 它只是分享了同样的姿态:

     currentDrawingNode =SCNNode(geometry: SCNBox(width: 1, height: 1, length: 0, chamferRadius: 0))
     currentDrawingNode.eulerAngles.x=self.cameraNode.eulerAngles.x currentDrawingNode.eulerAngles.y=self.cameraNode.eulerAngles.y

    同时,我创建了一个新的CAShapeLayer,它将包含一个跟随用户指针的触摸路径:

     currentDrawingLayer =CAShapeLayer()
     let material =SCNMaterial()
     material.diffuse.contents= currentDrawingLayer
     material.lightingModelName= SCNLightingModelConstant
     currentDrawingNode.geometry?.materials= [material]

    在 touchesMoved ( ) 上,我需要将主视图中的位置转换为几何图形的位置。 这个几何图元大小为 1,所以我需要将它转换为我的CAShapeLayer ( 任意设置为 512 x 512 ) 中的坐标,以添加它的路径。

    有一些步骤需要这样做,接触集中第一项的locationInView(),我将它传递给SceneKit场景中的hitTest() 。 为当前几何图形筛选的所有几何图形返回 array的SCNHitTestResults,然后简单地重缩放结果的localCoordinates以查找当前 CAShapeLayer:

    let locationInView = touches.first?.locationInView(view)
     iflet hitTestResult:SCNHitTestResult = sceneKitView.hitTest(locationInView!, options: nil).filter( { $0.node== currentDrawingNode }).first,
     currentDrawingLayer = currentDrawingLayer
     {
     let drawPath =UIBezierPath(CGPath: currentDrawingLayer.path!)
     let newX =CGFloat((hitTestResult.localCoordinates.x+0.5) *Float(currentDrawingLayerSize))
     let newY =CGFloat((hitTestResult.localCoordinates.y+0.5) *Float(currentDrawingLayerSize))
     drawPath.addLineToPoint(CGPoint(x: newX, y: newY))
     currentDrawingLayer.path= drawPath.CGPath }

    。而这就是 !

    这个项目的源代码在我的GitHub知识库中可以找到。 它是在 Xcode 7 beta 5下开发的,并在我的iPhone 6运行iOS测试。



    文章标签:控制  CORE  spa  Space  

    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语