SceneKit: понимание свойства поворота SCNNode

Цель состоит в том, чтобы увеличить длину SCNBox так, чтобы он рос только в положительном направлении оси z.

Этот ответ предлагает поиграть со свойством pivot.

Однако документация по свойству pivot скудна на странице SCNNode, а на странице SCNBox ничего нет.

Может кто-нибудь объяснить, как работает свойство pivot?


person Crashalot    schedule 03.03.2017    source источник


Ответы (3)


Изменение pivot узла концептуально аналогично вставке промежуточного узла между этим узлом и его родителем. Это может быть полезно в разных случаях. Одним из примеров является случай, когда центр геометрии узла находится не там, где вы ожидаете.

Например, если у вас есть SCNBox, его ограничивающая рамка

  • мин: (-0.5 * width, -0.5 * height, -0.5 * length)
  • макс: (+0.5 * width, +0.5 * height, +0.5 * length)
  • центр: (0.0, 0.0, 0.0)

Если вы хотите, чтобы length из SCNBox увеличивалось только по положительной оси Z, то вам нужно

  • мин: (-0.5 * width, -0.5 * height, 0.0)
  • макс: (+0.5 * width, +0.5 * height, length)
  • центр: (0.0, 0.0, +0.5 * length)

Ограничительная рамка геометрии никогда не изменится, но есть способы упорядочить узлы и изменить их ограничивающие рамки.


Решение 1. Промежуточный узел

Одним из распространенных решений при работе с преобразованиями является использование промежуточных узлов для лучшего понимания того, как применяются преобразования.

В вашем случае вы захотите изменить иерархию узлов с

- parentNode
  | - node
  |   * geometry
  |   * transform = SCNMatrix4MakeScale(...)

to

- parentNode
  | - intermediateNode
  |   * transform = SCNMatrix4MakeScale(...)
  |   | - node
  |   |   * geometry
  |   |   * transform = SCNMatrix4MakeTranslation(0, 0, +0.5 * length)

В этой новой иерархии центр ограничивающей рамки node по-прежнему равен (0.0, 0.0, 0.0), но центр ограничивающей рамки intermediateNode равен (0.0, 0.0, +0.5 * length).

Масштабируя intermediateNode вместо node, вы получите желаемый результат.

Решение 2. Сводка

Оказывается, именно это и делает свойство pivot:

node.pivot = SCNMatrix4MakeTranslation(0, 0, -0.5 * length);

Как только вы мысленно определили преобразование промежуточного узла, просто установите его inverse в свойство pivot.


Дополнительную информацию о свойстве pivot можно найти здесь: https://developer.apple.com/reference/scenekit/scnnode/1408044-pivot

Это очень похоже на свойство anchorPoint Core Animation для CALayer, за исключением того, что в Core Animation точка привязки указывается относительно ограничивающей рамки слоя (идет от 0 до 1 в процентах от ширины и высоты слоя), а в SceneKit это абсолютный.

person mnuages    schedule 05.03.2017
comment
Большое спасибо за это подробное объяснение. SceneKit великолепен, но он разочаровывает, потому что документация очень плохая, и я знаю, что это не ваша вина. И поскольку это так ново, вокруг не так много экспертов, которые помогут, если вы застряли. Планирует ли Apple выделять больше ресурсов для улучшения документации SceneKit в будущем? - person Crashalot; 06.03.2017

Скажем, у вас есть ящик, созданный следующим образом:

SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)

Точка поворота будет в центре этого прямоугольника, теперь вы хотите переместить ее к одному из краев. Это можно сделать, переместив опорный узел на 0,5. (Это половина ширины коробки или расстояние между центром и краем.)

boxNode.pivot = SCNMatrix4MakeTranslation(0, 0, -0.5)

Точка поворота теперь будет расположена в центре X, центре Y и нуле Z объекта. Если вы теперь масштабируете коробку, она будет расти только в положительном направлении Z.

person James P    schedule 03.03.2017
comment
Круто, это выглядит потрясающе. Попробую. Самое главное, где вы нашли эту документацию? Спасибо еще раз! - person Crashalot; 03.03.2017
comment
Я этого не делал, я просто экспериментировал с помощью ответа, который вы связали, и посмотрел на результаты. - person James P; 03.03.2017
comment
Кстати, вы хотели бы получить консультацию по SceneKit? Очень микрозадачи, такие как создание анимации ореола/ряби? - person Crashalot; 06.03.2017
comment
Спасибо, но я совсем новичок в SceneKit, пока только экспериментирую. - person James P; 06.03.2017
comment
Тогда микроконсультации могли бы принести пользу нам обоим: вы предлагаете скидку, поэтому мы выиграем от более низкой стоимости, а вы выиграете от того, что будете получать деньги за обучение за наши деньги. Что вы думаете? - person Crashalot; 07.03.2017

Похоже, вы хотите увеличить длину SCNBox (геометрия). Таким образом, вы можете просто увеличить свойство length. Ответ, который вы упомянули, касается свойства pivot. Как видно из документа:

Точка поворота для положения узла, поворота и масштаба.

Например, установив точку поворота на преобразование перемещения, вы можете расположить узел, содержащий геометрию сферы, относительно того места, где сфера будет лежать на полу, а не относительно ее центра.

person HaoDong    schedule 03.03.2017
comment
Спасибо, но увеличение длины увеличивает размер блока как по положительной, так и по отрицательной оси z. Нам нужно только увеличение по положительной оси z. - person Crashalot; 03.03.2017