如何在相机中绘制线节点与 iPhone 中的 Measure App 保持相同的大小? [英] How to draw line node keep same size in camera as Measure App in iPhone?

查看:17
本文介绍了如何在相机中绘制线节点与 iPhone 中的 Measure App 保持相同的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试将 AR 应用作为 iPhone 中的 Measure 默认应用.(我基于github上的TBXark/Ruler项目)

I try make an AR app as a Measure default app in iPhone. ( I base on project TBXark/Ruler on github)

我绘制了 startNode、endNode、圆柱线和 SCNText.但是我无法管理大小的比例,它只能在近处读取,并且在测量远平面检测时很小.

I draw startNode, endNode, cylinder line, and SCNText. But I can't manage the scale of size, it only readable in near, and so small when measure far plane detect.

我有两个问题:

  1. 如何在测量应用程序中拉近或拉远时保持大小节点、圆柱体和文本相同

  1. How to keep size node, cylinder and text same when draw near or far as Measure App

如何用背景绘制scntext并对齐与Measure App相同方向的圆柱线.

How to draw scntext with background and align the same direction cylinder line as Measure App.

这是我的线节点类:

class LineNode: NSObject {

let startNode: SCNNode
let endNode: SCNNode
var lineNode: SCNNode?
let textNode: SCNNode
let sceneView: ARSCNView?

// init func
init(startPos: SCNVector3,
     sceneV: ARSCNView,
     color: (start: UIColor, end: UIColor) = (UIColor(hexCss: 0xF1B426), UIColor(hexCss: 0xD43278)),
     font: UIFont = UIFont.boldSystemFont(ofSize: 8) ) {
    sceneView = sceneV

    let scale = 1 / 400.0
    let scaleVector = SCNVector3(scale, scale, scale)

    func buildSCNSphere(color: UIColor) -> SCNSphere {
        let dot = SCNSphere(radius: 1)
        dot.firstMaterial?.diffuse.contents = color
        dot.firstMaterial?.lightingModel = .constant
        dot.firstMaterial?.isDoubleSided = true
        return dot
    }
    // startNode
    startNode = SCNNode(geometry: buildSCNSphere(color: color.start))
    startNode.scale = scaleVector
    startNode.position = startPos
    sceneView?.scene.rootNode.addChildNode(startNode)

    // endNode
    endNode = SCNNode(geometry: buildSCNSphere(color: color.end))
    endNode.scale = scaleVector
    // line with start to end
    lineNode = CylinderLine(parent: sceneView!.scene.rootNode,
                            v1: startNode.position,
                            v2: endNode.position,
                            radius: 0.001,
                            radSegmentCount: 16,
                            color: UIColor.white)

    sceneView?.scene.rootNode.addChildNode(lineNode!)
    // text show measure line length
    let text = SCNText (string: "--", extrusionDepth: 0.1)
    text.font = font
    text.firstMaterial?.diffuse.contents = UIColor(hexCss: 0xffa800)
    text.firstMaterial?.lightingModel = .constant
    text.alignmentMode = CATextLayerAlignmentMode.center.rawValue
    text.truncationMode = CATextLayerTruncationMode.middle.rawValue
    text.firstMaterial?.isDoubleSided = true
    textNode = SCNNode(geometry: text)

    textNode.scale = SCNVector3(1 / 500.0, 1 / 500.0, 1 / 500.0)

    super.init()
}

// update end node realtime
public func updatePosition(pos: SCNVector3, camera: ARCamera?, unit: MeasurementUnit.Unit = MeasurementUnit.Unit.centimeter) -> Float {
    // update endNode
    let posEnd = updateTransform(for: pos, camera: camera)
    if endNode.parent == nil {
        sceneView?.scene.rootNode.addChildNode(endNode)
    }
    endNode.position = posEnd
    // caculate new mid
    let posStart = startNode.position
    let middle = SCNVector3((posStart.x + posEnd.x) / 2.0, (posStart.y + posEnd.y) / 2.0 + 0.002, (posStart.z + posEnd.z) / 2.0)
    // update text measure
    let text = textNode.geometry as! SCNText
    let length = posEnd.distanceFromPos(pos: startNode.position)
    text.string = MeasurementUnit(meterUnitValue: length).roundUpstring(type: unit)
    text.materials.first?.diffuse.contents = UIColor.orange
    textNode.setPivot()
    textNode.position = middle
    if textNode.parent == nil {
        sceneView?.scene.rootNode.addChildNode(textNode)
    }

    lineNode?.removeFromParentNode()
    lineNode = lineBetweenNodeA(nodeA: startNode, nodeB: endNode)
    sceneView?.scene.rootNode.addChildNode(lineNode!)

    return length
    }
}

推荐答案

我用它来更新比例,即使你远离它仍然可读

I use this to update scale if even if you stay far away it still readable

func updateScaleFromCameraForNodes(_ nodes: [SCNNode], fromPointOfView pointOfView: SCNNode , useScaling: Bool){
        nodes.forEach { (node) in

            //1. Get The Current Position Of The Node
            let positionOfNode = SCNVector3ToGLKVector3(node.worldPosition)

            //2. Get The Current Position Of The Camera
            let positionOfCamera = SCNVector3ToGLKVector3(pointOfView.worldPosition)

            //3. Calculate The Distance From The Node To The Camera
            let distanceBetweenNodeAndCamera = GLKVector3Distance(positionOfNode, positionOfCamera)

            let a = distanceBetweenNodeAndCamera*1.75
            if(useScaling) {
                node.simdScale = simd_float3(a,a,a)

            }

        }
        SCNTransaction.flush()
    }

然后在渲染器 updateAtTime 中调用它

then called it in the renderer updateAtTime

self.updateScaleFromCameraForNodes(self.nodesAdded, fromPointOfView:
self.cameraNode, useScaling: true)

这篇关于如何在相机中绘制线节点与 iPhone 中的 Measure App 保持相同的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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