Получить абсолютное положение относительно экрана SKEffectNode, поскольку оно деформировано с помощью SKWarpGeometryGrid - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть SKVideoNode в качестве дочернего элемента SKEffectNode, который позволяет мне наклонять видео, используя столбец 1 строка x 1 SKWarpGeometryGrid.

При перетаскивании пальца в каждом квадранте новые угловые координаты вычисляются в touchMoved (toPoint fingerPos: CGPoint), а затем SKWarpGeometryGrid обновляется в updateGrid ()

У меня также есть синий квадрат с центром в SKView (и, следовательно, в начальном центре видео). Мне бы хотелось, чтобы синий квадрат следовал за центром видео-узла, когда эффект-узел деформируется. Я не хочу, чтобы квадрат добавлялся как дочерний элемент effectNode, поскольку квадрат также будет деформирован.

Я пробовал различные комбинации параметров для преобразования (: to :) и преобразования (: из :)

, например

blueSquare?.position = self.convert(effectNode!.position, to: self)

… но синий квадрат никогда не двигается. Есть мысли?

код: (замените myFriend.mp4 на видеофайл для тестирования)

import SpriteKit
import GameplayKit

class GameScene: SKScene {

let warpGeometryGrid1Col = SKWarpGeometryGrid(columns: 1,rows: 1)

var warpGridPositions: [float2] = [
float2(0.0, 0.0),  float2(1.0, 0.0),
float2(0.0, 1.0),  float2(1.0, 1.0)]
var adjust: Float = 0.005
var previousPosX: CGFloat = 0
var previousPosY: CGFloat = 0
var topLeftX:Float = 0.0
var topLeftY:Float = 1.0
var topRightX:Float = 1.0
var topRightY:Float = 1.0
var bottomLeftX:Float = 0.0
var bottomLeftY:Float = 0.0
var bottomRightX:Float = 1.0
var bottomRightY:Float = 0.0

var blueSquare:SKSpriteNode?
var effectNode: SKEffectNode?

override func didMove(to view: SKView) {

// **** add a video file to the project
  let videoNode = SKVideoNode.init(fileNamed: "myFriend.mp4")
videoNode.size.width = self.frame.size.height/3*1.5
videoNode.size.height = self.frame.size.width/3*1.5
videoNode.play()

effectNode = SKEffectNode()
effectNode!.addChild(videoNode)
self.addChild(effectNode!)

blueSquare = SKSpriteNode.init(color: .blue, size: CGSize(width: 50, height: 50))
self.addChild(blueSquare!)
}

func updateGrid(){
warpGridPositions = [float2(bottomLeftX, bottomLeftY), float2(bottomRightX, bottomRightY),
                     float2(topLeftX, topLeftY), float2(topRightX, topRightY)]
effectNode!.warpGeometry = warpGeometryGrid1Col.replacingByDestinationPositions(positions: warpGridPositions)

//*********************************
//*********************************
// TRY TO ADJUST POSITION OF blueSquare AS EFFECT 
// NODE IS WARPED KEEPING IT CENTERED ON THE 
// EFFECT NODE'S CHILD VIDEO
blueSquare?.position = self.convert(effectNode!.position, to: self)
//*********************************
//*********************************
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}

func touchMoved(toPoint fingerPos : CGPoint) {
if fingerPos.y < 0{
  if fingerPos.x > 0{// bottom right
    if fingerPos.x > previousPosX {
      bottomRightX += adjust
    }
    if fingerPos.x < previousPosX {
      bottomRightX -= adjust
    }
    if fingerPos.y > previousPosY {
      bottomRightY += adjust
    }
    if fingerPos.y < previousPosY {
      bottomRightY -= adjust
    }
  }
  else{ // bottom left
    if fingerPos.x > previousPosX {
      bottomLeftX += adjust
    }
    if fingerPos.x < previousPosX {
      bottomLeftX -= adjust
    }
    if fingerPos.y > previousPosY {
      bottomLeftY += adjust
    }
    if fingerPos.y < previousPosY {
      bottomLeftY -= adjust
    }
  }
} else{
  // top right
  if fingerPos.x > 0{
    if fingerPos.x > previousPosX {
      topRightX += adjust
    }
    if fingerPos.x < previousPosX {
      topRightX -= adjust
    }
    if fingerPos.y > previousPosY {
      topRightY += adjust
    }
    if fingerPos.y < previousPosY {
      topRightY -= adjust
    }
  }
  else{ // top left
    if fingerPos.x > previousPosX {
      topLeftX += adjust
    }
    if fingerPos.x < previousPosX {
      topLeftX -= adjust
    }
    if fingerPos.y > previousPosY {
      topLeftY += adjust
    }
    if fingerPos.y < previousPosY {
      topLeftY -= adjust
    }
  }
}

updateGrid()
previousPosX = fingerPos.x
previousPosY = fingerPos.y
}


}

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

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

  override func didMove(to view: SKView) {

            // **** add a video file to the project
            let videoNode = SKVideoNode.init(fileNamed: "myFriend.mp4")
            videoNode.size.width = self.frame.size.height/3*1.5
            videoNode.size.height = self.frame.size.width/3*1.5
            videoNode.play()
            videoFrame =  (videoNode.frame)



        effectNode = SKEffectNode()
        effectNode!.addChild(videoNode)


        self.addChild(effectNode!)

        blueSquare = SKSpriteNode.init(color: .blue, size: CGSize(width: 50, height: 50))
        self.addChild(blueSquare!)
            blueSquare?.position = CGPoint.init(x: 100, y: 100)


    cachedValue = cacheFrame(relativePosition((blueSquare?.position)!, videoFrame))


    }

    var cachedValue : simd_quatd!
func relativePosition(_ point: CGPoint, _ frame: CGRect) -> CGPoint{
    return CGPoint.init(x: (point.x - frame.origin.x) / frame.size.width , y:
    (point.y - frame.origin.y) / frame.size.height
    )
}

func cacheFrame(_ point : CGPoint)-> simd_quatd {
    let x = Double(point.x)
    let y = Double(point.y)
  return  simd_quatd(vector:  double4([(1-x)*(1-y), x*(1-y), (1-x)*y, x*y]))
}

    func updateGrid(){
        warpGridPositions = [float2(bottomLeftX, bottomLeftY), float2(bottomRightX, bottomRightY),
                             float2(topLeftX, topLeftY), float2(topRightX, topRightY)]
        effectNode!.warpGeometry = warpGeometryGrid1Col.replacingByDestinationPositions(positions: warpGridPositions)
        let finalRatio = CGPoint(x: CGFloat( simd_dot( simd_quatd(vector:
    double4( warpGridPositions.map{Double($0.x)})) ,
                                               cachedValue   )),y:
                    CGFloat(  simd_dot(simd_quatd(vector:
        double4( warpGridPositions.map{Double($0.y)})) , cachedValue))
        )

         let   finalWidth = videoFrame.origin.x + CGFloat(finalRatio.x) * videoFrame.size.width

         let   finalHeight = videoFrame.origin.y + CGFloat(finalRatio.y) * videoFrame.size.height
         blueSquare?.position = CGPoint.init(x:finalWidth , y: finalHeight)

    }
0 голосов
/ 08 ноября 2018

Если effectNode начинается с центра SKScene, вычисление является прямым. ViewFrame может быть кэширован для ускорения расчета.

   var videoFrame : CGRect!
        override func didMove(to view: SKView) {

            // **** add a video file to the project
            let videoNode = SKVideoNode.init(fileNamed: "myFriend.mp4")
            videoNode.size.width = self.frame.size.height/3*1.5
            videoNode.size.height = self.frame.size.width/3*1.5
            videoNode.play()
            videoFrame =  (videoNode.frame)

        effectNode = SKEffectNode()
        effectNode!.addChild(videoNode)

        self.addChild(effectNode!)

        blueSquare = SKSpriteNode.init(color: .blue, size: CGSize(width: 50, height: 50))
        self.addChild(blueSquare!)
    }

    func updateGrid(){
        warpGridPositions = [float2(bottomLeftX, bottomLeftY), float2(bottomRightX, bottomRightY),
                             float2(topLeftX, topLeftY), float2(topRightX, topRightY)]
        effectNode!.warpGeometry = warpGeometryGrid1Col.replacingByDestinationPositions(positions: warpGridPositions)
         let finalRatio =  ( warpGridPositions.reduce(float2(),+) / 4.0)
         let   finalWidth = videoFrame.origin.x + CGFloat(finalRatio.x) * videoFrame.size.width
         let   finalHeight = videoFrame.origin.y + CGFloat(finalRatio.y) * videoFrame.size.height
         blueSquare?.position = CGPoint.init(x:finalWidth , y: finalHeight)

    }

Надеюсь, что нет проблем.

...