ARKIT: как перемещать объекты в воздухе, как в приложении GiPHY World

Я реализовал методы для перемещения объекта, находящегося поверх поверхности, с помощью UIPanGesture и техники raycasting относительно плоскости... для определения новой координаты объекта при перетаскивании.

Но что, если объект находится в воздухе, вы не можете использовать raycast против какой-либо плоскости. Я заметил, что приложение GIPHY World позволяет переключаться между двумя режимами:

  1. Обнаружение плоскости (где объекты разрешено размещать ТОЛЬКО на поверхности)
  2. Свободный режим (где объекты можно размещать ТОЛЬКО плавающими перед камерой)

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

Интересно, можете ли вы, ребята, предложить какой-нибудь код для преобразования перетаскивания 2D-экрана в то, как движется 3D-объект. Бывший.

  • Если вы находитесь перед объектом, перетаскивание на экране ВВЕРХ/ВНИЗ приведет к перемещению объекта по координате Z... близко или далеко.
  • Но если вы физически переместитесь в сторону... и снова перетащите экран ВВЕРХ/ВНИЗ, объект теперь перемещается по координате X. <--- Как они это делают ?

Вот видео как это работает. https://youtu.be/16iMMuwjfIc

Здесь вы можете увидеть, что я пробовал, основываясь на ответе @Vollan ниже. Вы можете видеть, что репозиционирование не работает, как приложение GiPHY. https://youtu.be/ZoWj6WRBY58


person omarojo    schedule 04.05.2018    source источник


Ответы (1)


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

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

1: Мировое положение поместит начало осей Z, X, Y в то место, где находилась камера, когда вы начали сеанс AR. 2: Положение камеры означает, что источник будет следовать за вами и будет привязан к камере. Это приведет к тому, что узел всегда будет трехмерным.

Теперь, если вы выберете мировую позицию и решите обойти узел или начальную позицию, например, 90 градусов. Тогда у вас будет другой угол в начале оси, поскольку оси Z и X поменяются местами. Преобразование UP/DOWN в Z в X.

Во-вторых, я использую этот код:

@objc func adjustWindow(_ gesture: UIPinchGestureRecognizer) {
    var startPosition: CGPoint = CGPoint(x: 0, y: 0)

    // Fetch location for touch in sceneView
    let location: CGPoint = gesture.location(in: sceneView)

    // Fetch targets at the current location
    let hits = self.sceneView.hitTest(location, options: nil)

    // Check if it's a node and it's a window node that has been touched
    guard let node = hits.first?.node, node.name == "name" else {return}

    // Make sure user is using 1 finger to move the view
    if gesture.numberOfTouches == 1 {
        switch gesture.state {
        case .failed, .cancelled, .ended:
            // Reset position after finished
            startPosition = CGPoint(x: 0, y: 0)
            break
        case .began:
            // Save start position, so that we can check how far the user have moved
            startPosition = location
        case .changed:
            // Fetch new x and y position
            let deltaX = Float(location.x - startPosition.x)/20
            let deltaY = Float(location.y - startPosition.y)/20

            // Transform and apply the new location
            let box = node.transform
            let translation = SCNMatrix4MakeTranslation(deltaX, deltaY, 1)
            let newTrans = SCNMatrix4Mult(box, translation)
            node.transform = newTrans

            node.localTranslate(by: SCNVector3Make(deltaX, deltaY, 1))
            // Set new location
            startPosition = location
        default:
            break
        }
        // Make sure user is using 2 fingers for scaling the view
    }
 }

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

Реализация ARSessionDelegate и

 var matrix: matrix_float4x4!

    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        // Fetch and store current camera position
        matrix = frame.camera.transform
    }

Будет получать текущее положение камеры в любое время, поскольку оно обновляется при перемещении камеры. Я пока не понял, как это применить. Возможно, с помощью:

let translation = SCNMatrix4MakeTranslation(deltaX*matrix.m41, deltaY*matrix.m42, 1*matrix.m43)

Или что-то.

Удачи.

person Vollan    schedule 04.05.2018
comment
мммм В вашем первом абзаце я думаю, вы поняли, что я имел в виду. Но то, как вы реализовали перемещение узла, не учитывает тот факт, что вы физически перемещаетесь вокруг плавающего объекта (также я не знаю, связана ли секция касания двумя пальцами). И... вы перемещаете ВСЕ объекты в сцене? Извините, я реализовал первый сенсорный раздел с одним пальцем, и он не сделал того, что я ожидал :( :( - person omarojo; 04.05.2018
comment
Да, в этой функции я перемещал все объекты в сцене, и извините за двухпалый. Я обновил код сейчас, чтобы он был несколько лучше. Можете ли вы объяснить, что происходит? Он перемещает оси X и Y для меня, когда я перетаскиваю, и если я перемещаю объект, он путается. - person Vollan; 04.05.2018
comment
Я действительно хотел, чтобы он перемещался по X, Z, а не по X, Y. Я только что провел рефакторинг. И да, это работает. Но, как вы упомянули ... если я изменю угол, под которым я смотрю на объект ... тогда оси инвертируются ... или, скорее, ... остаются неизменными. Позвольте мне сделать видео, чтобы показать вам. - person omarojo; 04.05.2018
comment
Не беспокойтесь о видео, я понимаю, что вы имеете в виду, к сожалению, я не смог исправить это самостоятельно. Так что не могу помочь вам в этом вопросе :( - person Vollan; 04.05.2018
comment
Отредактируйте мой ответ внизу. Хоть есть над чем работать :) - person Vollan; 04.05.2018
comment
@omarojo я нашел решение здесь: stackoverflow.com/questions/43237805/ - person Vollan; 07.05.2018