我正在制作一个简单的测量应用程序。目前,我将球体放置为SCNNodes
,并在节点之间出现了一个标签,该标签显示了从节点1到节点2的线的长度。
这是创建标签的方式:
func addLabel() {
let plane = SCNPlane(width: 0.07, height: 0.02)
plane.cornerRadius = plane.height / 10
let sks = SKScene(size: CGSize(width: plane.width * 10e3, height: plane.height * 10e3))
sks.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 0.7)
currentLbl = SKLabelNode(text: "")
currentLbl.fontSize = 110
currentLbl.fontName = "Helvetica"
currentLbl.verticalAlignmentMode = .center
currentLbl.position = CGPoint(x: sks.frame.midX, y: sks.frame.midY)
currentLbl.fontColor = .white
sks.addChild(currentLbl)
let material = SCNMaterial()
material.isDoubleSided = true
material.diffuse.contents = sks
material.diffuse.contentsTransform = SCNMatrix4Translate(SCNMatrix4MakeScale(1, -1, 1), 0, 1, 0)
plane.materials = [material]
let node = SCNNode(geometry: plane)
node.constraints = [SCNBillboardConstraint()]
node.position = SCNVector3Make(0, 0, 0)
let (minBound, maxBound) = node.boundingBox
node.pivot = SCNMatrix4MakeTranslation( (maxBound.x + minBound.x)/2, minBound.y, 0.02/2)
lblNodes.append(node)
currentLblNode = node
sceneView.scene.rootNode.addChildNode(node)
}
我想对这些标签节点的比例(在我的更新函数中)应用数学方程式,以保持两米的可读性。
var myNodes: [SCNNode] = []
let s = getMagicScalingNumber()
说我获得了上面的比例因子,并且有一个SCNNode数组,如何缩放所有节点及其各自的子节点,以便它们在视觉上保持比例。
如果SCNTransformConstraint()
是这个选项,我将感谢一个实现它的示例。
修改:为澄清起见,我已经尝试过
currentLblNode.scale = SCNVector3Make(s, s, s)
似乎无效。
答案 0 :(得分:4)
我知道这已经很晚了,但是我整理了一个例子,应该指出正确的方向。
在您的示例中,您实际上是在创建一个包含标签等的持有人SCNNode。
您可以将它们存储到[SCNNode]数组中,然后像这样转换它们的比例:
//--------------------------
// MARK: - ARSCNViewDelegate
//--------------------------
extension ViewController: ARSCNViewDelegate{
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
if !nodesAdded.isEmpty, let currentCameraPosition = self.sceneView.pointOfView {
updateScaleFromCameraForNodes(nodesAdded, fromPointOfView: currentCameraPosition)
}
}
}
class ViewController: UIViewController {
@IBOutlet var sceneView: ARSCNView!
var nodesAdded = [SCNNode]()
//-----------------------
// MARK: - View LifeCycle
//-----------------------
override func viewDidLoad() {
super.viewDidLoad()
//1. Generate Our Three Box Nodes
generateBoxNodes()
//2. Run The Session
let configuration = ARWorldTrackingConfiguration()
sceneView.session.run(configuration)
sceneView.delegate = self
}
/// Generates Three SCNNodes With An SCNBox Geometry & Places Them In A Holder Node
func generateBoxNodes(){
//1. Create An SCNNode To Hold All Of Our Content
let holderNode = SCNNode()
//2. Create An Array Of Colours For Each Face
let colours: [UIColor] = [.red, .green, .blue, .purple, .cyan, .black]
//3. Create An SCNNode Wih An SCNBox Geometry
let boxNode = SCNNode()
let boxGeometry = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0.01)
boxNode.geometry = boxGeometry
//4. Create A Different Material For Each Face
var materials = [SCNMaterial]()
for i in 0..<5{
let faceMaterial = SCNMaterial()
faceMaterial.diffuse.contents = colours[i]
materials.append(faceMaterial)
}
//5. Set The Geometries Materials
boxNode.geometry?.materials = materials
//6. Create Two More Nodes By Cloning The First One
let secondBox = boxNode.flattenedClone()
let thirdBox = boxNode.flattenedClone()
//7. Position Them In A Line & Add To The Scene
boxNode.position = SCNVector3(-0.2, 0, 0)
secondBox.position = SCNVector3(0, 0, 0)
thirdBox.position = SCNVector3(0.2, 0, 0)
holderNode.addChildNode(boxNode)
holderNode.addChildNode(secondBox)
holderNode.addChildNode(thirdBox)
holderNode.position = SCNVector3(0, 0, -1)
self.sceneView.scene.rootNode.addChildNode(holderNode)
nodesAdded.append(holderNode)
}
/// Updates The Contents Of Each Node Added To Our NodesAdded Array
///
/// - Parameters:
/// - nodes: [SCNNode]
/// - pointOfView: SCNNode
func updateScaleFromCameraForNodes(_ nodes: [SCNNode], fromPointOfView pointOfView: SCNNode){
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)
//4. Animate Their Scaling & Set Their Scale Based On Their Distance From The Camera
SCNTransaction.begin()
SCNTransaction.animationDuration = 0.5
switch distanceBetweenNodeAndCamera {
case 0 ... 0.5:
node.simdScale = simd_float3(0.25, 0.25, 0.25)
case 0.5 ... 1:
node.simdScale = simd_float3(0.5, 0.5, 0.5)
case 1 ... 1.5:
node.simdScale = simd_float3(1, 1, 1)
case 1.5 ... 2:
node.simdScale = simd_float3(1.5, 1.5, 1.5)
case 2 ... 2.5:
node.simdScale = simd_float3(2, 2, 2)
case 2.5 ... 3:
node.simdScale = simd_float3(2.5, 2.5, 2.5)
default:
print("Default")
}
SCNTransaction.commit()
}
}
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) }
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) }
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
}
在这里,我只是设置“随机”值以说明比例尺的概念,具体取决于距相机的距离。
为了更好地说明这一点,这里提供了一个小样:
const styles = {root: {
height: 500,
width: 200},};
希望这对您有帮助...