Придайте своей новой реальности новый облик
Вы спрашиваете себя, почему вы хотите изменить текстуру на узле (узел - это любой объект в сцене SceneKit)?
Есть множество причин. Самый простой - вам нужна индикация вашего взаимодействия с узлом. Возможно, у вас есть игра с дополненной реальностью и вы хотите сообщить игрокам, что состояние игры изменилось. Может быть, статические текстуры время от времени надоедают.
Какой бы ни была причина, я здесь, чтобы предоставить простое руководство о том, как изменять текстуры в работающем приложении ARKit с помощью сенсорных жестов.
Начиная
Начнем с создания нового проекта. Вместо того, чтобы реализовывать ARSCNView
и шаблон с нуля, выберите приложение дополненной реальности в качестве шаблона и убедитесь, что SceneKit является выбранной технологией контента.
Прежде чем вы начнете какой-либо код, нам нужно добавить несколько изображений для нашего проекта. Для этого конкретного приложения я выбрал тему солнечной системы и собрал текстуры для Земли, Луны и Солнца.
Совершенно верно - мы собираемся создавать планетные тела с помощью нашего приложения. Обязательно назовите их earth
, moon
и sun
соответственно и поместите их прямо в папку Assets.xcassets
.
В ViewController.swift
начните с объявления следующих переменных чуть выше метода viewDidLoad()
:
let textures = ["earth", "moon", "sun"] var currentIndex = 0 var currentTexture = ""
Убедитесь, что строки в массиве текстур имеют те же точные имена, что и текстуры в папке с ресурсами. Внутри метода viewDidLoad()
замените там, где написано SCNScene(named: “art.scnassets/ship.scn”)!
, на SCNScene()
. Под этой строкой инициализируйте currentTexture
первым элементом в textures
, используя currentTexture = textures[currentIndex]
.
После метода viewWillDisappear()
создайте следующую функцию:
func createSphere() -> SCNNode { let sphere = SCNSphere(radius: 1) sphere.firstMaterial?.diffuse.contents = UIImage(named: currentTexture) let sphereNode = SCNNode(geometry: sphere) sphereNode.name = "sphere" sphereNode.position = SCNVector3(0, 0, -3) return sphereNode }
Само собой разумеется, что эта функция создает сферу в нашем трехмерном пространстве. Мы задаем сфере radius
1
метров (в соответствии с единицей измерения ARKit по умолчанию) и назначаем ей текстуру currentTexture
, которая должна быть earth
.
Затем мы создаем SCNNode()
и назначаем геометрию его сферы, а также даем ей имя sphere
, что будет важно при изменении текстуры. Затем мы помещаем его в трех метрах от камеры, когда приложение запускается и возвращается sphereNode
.
В viewDidLoad()
добавьте следующее под тем местом, где мы присвоили currentTexture
:
sceneView.scene.rootNode.addChildNode(createSphere())
Протестируйте приложение на своем телефоне, и, если все пойдет хорошо, вы должны увидеть перед собой Землю дополненной реальности.
Жесткие жесты
Теперь приступим к изменению текстур с помощью сенсорного жеста. Под методом createSphere()
реализуйте touchesBegan(_:with:)
. Обратите внимание, что есть и другие способы реализовать сенсорный жест - это только один из них. Добавьте следующий код внутрь touchesBegan
:
let touch = touches.first! if touch.view == self.sceneView { let viewTouchLocation:CGPoint = touch.location(in: sceneView) guard let result = sceneView.hitTest(viewTouchLocation, options: nil).first else { return } if result.node.name == "sphere" { let node = result.node currentIndex = currentIndex == 0 ? 1 : currentIndex == 1 ? 2 : 0 currentTexture = textures[currentIndex] node.geometry?.firstMaterial?.diffuse.contents = currentTexture } }
Давайте рассмотрим этот кодовый блок.
Во-первых, мы получаем первый случай обнаружения касания.
Затем мы проверяем, находится ли касание в пределах sceneView
(если вы следовали инструкциям, sceneView
по умолчанию должен покрывать весь экран телефона, потому что у него автоматически нулевые поля с каждой стороны).
Затем мы получаем CGPoint
координаты точки касания относительно экрана.
Затем мы убеждаемся, что запускаем sceneView
’s hitTest
, назначая его result
; в противном случае мы return
.
На этом этапе код может проверить, касаемся ли мы узла. Если имя узла, которого мы касаемся, sphere
(которое мы использовали ранее), то нам нужно изменить текстуру сферы. Поскольку у меня всего три текстуры, я использую тернарный оператор для цикла currentIndex
от 0 ➡ 1 ➡ 2, а затем обратно до 0. Затем я переназначаю currentTexture
. И, наконец, я назначаю нашему узлу новый материал.
Ух! Запустите свой код, и вы должны получить такой результат, когда коснетесь сферы:
Это все! Я надеюсь, что это даст вам отправную точку для изменения текстур в ARKit. Вы можете ознакомиться с полным исходным кодом здесь.