1

I don't understand how node scaling on nodes work.

I'm trying to understand how the code on Apple's Creating Face Based AR Experiences sample project works. Specifically, I'm trying to understand the TransformVisualization.swift file and the transformations applied to its nodes.

The method addEyeTransformNodes() is called and left and right eye nodes are both scaled using the simdScale properties. That's the part I'm confused about.

I tried scaling the same node using .scale and .simdScale properties, but both of them did nothing.

Moreover, what's more confusing is the fact that even though the values for .simdPivot are greater than 1 the node is scaled down. I expected nodes to scale up.

Why would we need to set .simdPivot to scale the nodes but not .scale and .simdScale properties?

Here's the function I'm talking about.

func addEyeTransformNodes() {
  guard #available(iOS 12.0, *), let anchorNode = contentNode else { return }

  // Scale down the coordinate axis visualizations for eyes.
  rightEyeNode.simdPivot = float4x4(diagonal: float4(3, 3, 3, 1))
  leftEyeNode.simdPivot = float4x4(diagonal: float4(3, 3, 3, 1))

  anchorNode.addChildNode(rightEyeNode)
  anchorNode.addChildNode(leftEyeNode)
}

Here's what I tried:

func addEyeTransformNodes() {
  guard #available(iOS 12.0, *), let anchorNode = contentNode else { return }

  // Does nothing
  rightEyeNode.simdScale = float3(3, 3, 3)
  // Does nothing
  leftEyeNode.scale = SCNVector3(x: 3, y: 3, z: 3)

  anchorNode.addChildNode(rightEyeNode)
  anchorNode.addChildNode(leftEyeNode)
}

I expected to scale the node with the way I did it, but nothing happened.

Looking forward to your answers and help.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
ddeger
  • 137
  • 8

1 Answers1

2

If you need to offset a pivot (before applying rotate and/or scale) point use simdPivot instance property.

Use my testing code to find out how it works:

let sphereNode1 = SCNNode(geometry: SCNSphere(radius: 1))
sphereNode1.geometry?.firstMaterial?.diffuse.contents = UIColor.red
sphereNode1.position = SCNVector3(-5, 0, 0)
scene.rootNode.addChildNode(sphereNode1)

let sphereNode2 = SCNNode(geometry: SCNSphere(radius: 1))
sphereNode2.geometry?.firstMaterial?.diffuse.contents = UIColor.green
sphereNode2.simdPivot.columns.3.x = -1

sphereNode2.scale = SCNVector3(2, 2, 2)           // WORKS FINE
//sphereNode2.simdScale = float3(2, 2, 2)         // WORKS FINE

scene.rootNode.addChildNode(sphereNode2)

let sphereNode3 = SCNNode(geometry: SCNSphere(radius: 1))
sphereNode3.geometry?.firstMaterial?.diffuse.contents = UIColor.blue
sphereNode3.position = SCNVector3(5, 0, 0)
scene.rootNode.addChildNode(sphereNode3)

Pivot offset is x: -1:

enter image description here

Pivot offset is x: 0:

enter image description here

Using init(diagonal:) initializer helps you creating a new 4x4 Matrix with the specified vector on the main diagonal. This method has an issue: it scales down objects when you're assigning diagonal values greater than 1, and vice versa. So, if you want to scale up character's eyes use the following approach as a workaround:

rightEyeNode.simdPivot = float4x4(diagonal: float4(1/3, 1/3, 1/3, 1))
leftEyeNode.simdPivot = float4x4(diagonal: float4(1/3, 1/3, 1/3, 1))

I think Apple engineers will fix this issue in the future.

Hope this helps.

Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
  • Hi ARGeo, thanks for the answer. Unfortunately, I think it doesn't answer my question. As shown above Apple used .simdPivot to scale down the node. I'm trying to understand 1) why setting either .scale or .simdScale doesn't scale the nodes given situation above, 2) why setting float4(3,3,3,1) on .simdPivot scales down the node, I expected nodes to scale up. Hopefully, you can shed light on these. My understanding of working with matrices and .simd is based on this: https://developer.apple.com/documentation/accelerate/simd/working_with_matrices – ddeger May 08 '19 at 06:35
  • 1
    Thanks for the update. You are certainly correct about the issue with the init(diagonal:). I was able to scale up the node based on your suggestion. The only question that remains is why setting either node.scale or node.simdScale doesn't scale the nodes. Can you explain that please? – ddeger May 08 '19 at 07:05
  • `.simdScale = float3(3, 3, 3)` and `.scale = SCNVector3(x: 3, y: 3, z: 3)` are working fine. Test them outside a function. You'll see it's OK. I suppose the problem is an `anchorNode`. – Andy Jazz May 08 '19 at 07:18
  • I've supplied my code with `sphereNode2.scale = SCNVector3(2, 2, 2)`. It works. I've just tested `.simdScale = float3(3, 3, 3)`. It works too. – Andy Jazz May 08 '19 at 07:20
  • At first get rid of `#available(iOS 12.0, *)` and see if it works. – Andy Jazz May 08 '19 at 07:23
  • If it doesn't help, the problem is Anchors (or any other logic). But scale works. – Andy Jazz May 08 '19 at 07:37
  • So scale is functioning. Anchor node's issue is another question)) Publish it. Let's close this one. – Andy Jazz May 08 '19 at 07:44
  • I got rid of ```#available(iOS 12.0, *)```, it accomplished nothing. I tested .simdScale and .scale on a separate and new project. They all seem to work fine. I also tried scaling using .simdPivot that also works as you pointed out. I'm confused why given the situation above why I can't set .simdScale and .scale properties. It might be the anchorNode. It's a SCNNode. Maybe you know why this doesn't work the way it should? There's method called ```func(_:didUpdate:for:)``` where for instance ```rightEyeNode.simdTransform = faceAnchor.rightEyeTransform```. Maybe this causes the problem? – ddeger May 08 '19 at 07:46