我正在iOS上使用SceneKit开发一些代码,而在我的代码中,我想确定全局z平面上的x和y坐标,z是0.0,x和y由点击手势确定.我的设置如下:
override func viewDidLoad() {
    super.viewDidLoad()

    // create a new scene
    let scene = SCNScene()

    // create and add a camera to the scene
    let cameraNode = SCNNode()
    let camera = SCNCamera()
    cameraNode.camera = camera
    scene.rootNode.addChildNode(cameraNode)
    // place the camera
    cameraNode.position = SCNVector3(x: 0,y: 0,z: 15)

    // create and add an ambient light to the scene
    let ambientLightNode = SCNNode()
    ambientLightNode.light = SCNLight()
    ambientLightNode.light.type = SCNLightTypeAmbient
    ambientLightNode.light.color = UIColor.darkGrayColor()
    scene.rootNode.addChildNode(ambientLightNode)

    let triangleNode = SCNNode()
    triangleNode.geometry = defineTriangle();
    scene.rootNode.addChildNode(triangleNode)

    // retrieve the SCNView
    let scnView = self.view as SCNView

    // set the scene to the view
    scnView.scene = scene

    // configure the view
    scnView.backgroundColor = UIColor.blackColor()
    // add a tap gesture recognizer
    let tapGesture = UITapGestureRecognizer(target: self,action: "handleTap:")
    let gestureRecognizers = NSMutableArray()
    gestureRecognizers.addobject(tapGesture)
    scnView.gestureRecognizers = gestureRecognizers
}

func handleTap(gestureRecognize: UIGestureRecognizer) {
    // retrieve the SCNView
    let scnView = self.view as SCNView
    // check what nodes are tapped
    let p = gestureRecognize.locationInView(scnView)
    // get the camera
    var camera = scnView.pointOfView.camera

    // screenZ is percentage between z near and far
    var screenZ = Float((15.0 - camera.zNear) / (camera.zFar - camera.zNear))
    var scenePoint = scnView.unprojectPoint(SCNVector3Make(Float(p.x),Float(p.y),screenZ))
    println("tapPoint: (\(p.x),\(p.y)) scenePoint: (\(scenePoint.x),\(scenePoint.y),\(scenePoint.z))")
}

func defineTriangle() -> SCNGeometry {

    // Vertices
    var vertices:[SCNVector3] = [
        SCNVector3Make(-2.0,-2.0,0.0),SCNVector3Make(2.0,SCNVector3Make(0.0,2.0,0.0)
    ]

    let vertexData = NSData(bytes: vertices,length: vertices.count * sizeof(SCNVector3))
    var vertexSource = SCNGeometrySource(data: vertexData,semantic: SCNGeometrySourceSemanticVertex,vectorCount: vertices.count,floatComponents: true,componentsPerVector: 3,bytesPerComponent: sizeof(Float),dataOffset: 0,dataStride: sizeof(SCNVector3))

    // normals
    var normals:[SCNVector3] = [
        SCNVector3Make(0.0,0.0,1.0),1.0)
    ]

    let normalData = NSData(bytes: normals,length: normals.count * sizeof(SCNVector3))
    var normalSource = SCNGeometrySource(data: normalData,semantic: SCNGeometrySourceSemanticnormal,vectorCount: normals.count,dataStride: sizeof(SCNVector3))

    // Indexes
    var indices:[CInt] = [0,1,2]
    var indexData  = NSData(bytes: indices,length: sizeof(CInt) * indices.count)
    var indexElement = SCNGeometryElement(
        data: indexData,primitiveType: .Triangles,primitiveCount: 1,bytesPerIndex: sizeof(CInt)
    )

    var geo = SCNGeometry(sources: [vertexSource,normalSource],elements: [indexElement])

    // material
    var material = SCNMaterial()
    material.diffuse.contents  = UIColor.redColor()
    material.doubleSided = true
    material.shininess = 1.0;
    geo.materials = [material];

    return geo
}

如你看到的.我有一个三角形,它是4单位高,4单位宽,并设置在以x,y(0.0,0.0)为中心的z平面(z = 0)上.相机是默认的SCNCamera,它看起来是负z方向,我把它放在(0,15). zNear和zFar的默认值分别为1.0和100.0.在我的handleTap方法中,我取得水龙头的x和y屏幕坐标,并尝试找到z = 0.0的x和y全局场景坐标.我正在调用unprojectPoint.

unprojectPoint的文档表示

Unprojecting a point whose z-coordinate is 0.0 returns a point on the
near clipping plane; unprojecting a point whose z-coordinate is 1.0
returns a point on the far clipping plane.

虽然没有具体说,对于近距离和远平面之间的线性关系之间的点,我已经做出了这个假设,并将screenZ的值计算为近平面与远平面之间的距离百分比z = 0飞机位于.为了检查我的答案,我可以点击三角形附近的角落,因为我知道它们在全局坐标中的位置.

我的问题是,我没有得到正确的值,当我开始更改相机上的zNear和zFar剪辑平面时,我没有获得一致的值.所以我的问题是,我该怎么办?最后,我要创建一个新的几何图形,并将其放在z平面上,对应于用户点击的位置.

在此先感谢您的帮助.

解决方法

3D图形管线中的典型深度缓冲区 are not linear.透视分区 causes depths in normalized device coordinates to be on a different scale.( See also here.)

所以你要进入unprojectPoint的z坐标并不是你想要的.

那么如何才能找到在世界空间中匹配一个平面的归一化深度坐标?那么,如果那架飞机与摄像机是正交的 – 那就是你的帮助.那么你需要做的就是在那架飞机上投射一点:

let projectedOrigin = gameView.projectPoint(SCNVector3Zero)

现在,您可以在三维视图中拥有世界起源的位置归一化深度空间.要将2D视图空间中的其他点映射到此平面上,请使用此矢量中的z坐标:

let vp = gestureRecognizer.locationInView(scnView)
let vpWithZ = SCNVector3(x: vp.x,y: vp.y,z: projectedOrigin.z)
let worldPoint = gameView.unprojectPoint(vpWithZ)

这让您在世界空间中将点击/分接位置映射到z = 0平面,适合用作节点的位置,如果要向用户显示该位置.

(请注意,只要映射到垂直于摄像机视图方向的平面,此方法才有效.如果要将视图坐标映射到不同面向的表面,则vpWithZ中的归一化深度值不会不变.)

如何正确使用iOS(Swift)SceneKit SCNSceneRenderer unprojectPoint的更多相关文章

  1. ios – 确定核心音频AudioBuffer中的帧数

    我正在尝试访问iPhone/iPad上的音频文件的原始数据.我有以下代码,这是我需要的路径的基本开始.但是,一旦我有了一个AudioBuffer,我就不知道该怎么做了.基本上我不知道如何判断每个缓冲区包含多少帧,因此我无法从它们中可靠地提取数据.我是处理原始音频数据的新手,所以我对如何最好地读取AudioBuffer结构的mData属性有任何建议.我在过去也没有做过很多关于void指针的事情,所以在这种情况下对它的帮助也会很棒!

  2. iOS – 生成并播放无限简单的音频(正弦波)

    我正在寻找一个非常简单的iOS应用程序,它带有一个启动和停止音频信号的按钮.信号只是一个正弦波,它将在整个播放过程中检查我的模型,并相应地改变音量.我的困难与任务的不确定性有关.我理解如何构建表格,填充数据,响应按钮按下等等;然而,当谈到只是无限期地继续时,我有点卡住了!任何指针都会很棒!

  3. ios – SceneKit.哪种方式起来了?

    似乎大多数3D创作应用程序使用Z作为“向上”轴.而SceneKit使用Y作为’向上’轴.SceneKit允许您将场景加载为Collada.DAE文件.通过以下任一方式加载场景时:要么您可以指定选项,包括SCNScenesourceConvertToYUpKey和SCNScenesourceConvertUnitsToMetersKey.相应地设置这些,我期望当我将它们添加到从加载场景中的节点构造的

  4. 如何在iOS 11 ARKit-Scenekit中为SCNNode创建边框以指示其选择?

    如何绘制边框以突出显示SCNNode并向用户指示该节点已被选中?在我的项目中,用户可以放置多个虚拟对象,用户可以随时选择任何对象.选择后,我应该向用户显示高亮显示的3D对象.有没有办法直接实现这个或在SCNNode上绘制边框?

  5. ios – 在球体表面SceneKit上写文字?

    我想知道是否有一种方法可以在SceneKit中沿着球体对象的表面写入文本.我知道如果我有一个图像,我会在表面上放置纹理并实现这种效果,但我想知道我是否可以在球体表面上以某种方式动态添加文本.任何的想法?

  6. ios – Swift Scenekit – 居中SCNText – getBoundingBoxMin:Max问题

    享受SCNText上的alignmentMode选项.谷歌搜索周围看起来像alignmentMode和containerFrame有问题.我发现的替代方案建议使用获取边界框功能来查找文本大小,然后相应地手动调整.很棒,除了我不能让功能工作.当我试图得到两个向量时,我得到一个错误:‘SCNVector3’无法转换为’UnsafeMutablePointer”我在几何和节点上得

  7. ios – 永远动画SCNNode – SceneKit,Swift

    我想永远动画2个立方体,直到用户点击其中一个.动画应该像∞一样.这些是我想要动画的sceneView中的我的立方体:我试图用嵌套动画做到这一点,它确实部分工作.现在,由于动画总是等到它们在开始新动画之前完成,它看起来并不光滑.在继续开发∞动画之前,我想知道是否有更好的方式.这是我目前的代码:输出显示以下内容:log0,log5,log6,log1,log2,log4,log2…解决方法如果要为SCNNode设置动画,请让节点运行SCNAction.迅速:Objective-C的:上面的代码将永久地上下调整

  8. xcode – 物理模拟的SceneKit更新方法

    我玩过精灵套件,并使用更新方法设置每个时间步骤处理的东西.我正试图学习一些快速的场景套件,似乎无法找到相应的.你能指点一下为SceneKit实现更新方法的例子吗?

  9. ios – 核心音频离线渲染GenericOutput

    等正在产生这些问题.尝试努力,它会工作.不要放弃:-).核心音频在处理低级音频时非常强大和有用.这是我从最近几周学到的东西.享受:-D…

  10. 如何正确使用iOS(Swift)SceneKit SCNSceneRenderer unprojectPoint

    那么,如果那架飞机与摄像机是正交的–那就是你的帮助.那么你需要做的就是在那架飞机上投射一点:现在,您可以在三维视图中拥有世界起源的位置归一化深度空间.要将2D视图空间中的其他点映射到此平面上,请使用此矢量中的z坐标:这让您在世界空间中将点击/分接位置映射到z=0平面,适合用作节点的位置,如果要向用户显示该位置.

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部