1

I have some camera with perspective projection and object in the (0,0,0). I computed "bounding frame"(size in pixels on screen) of this object according to this camera and scaled it to fit the screen size. And now it in the middle of screen.

Frame of the scnView is equal to the screen size and I have some UI components above this view(e.g. navigation bar and some big transparent view in the bottom of view). The scnView has some fullscreen background and this object can be scaled/moved/... therefore I need scnview to be fullscreen.

smth like that

Then I move this object in the middle of "clear area" (the area with absence of UIComponents) and see the bottom of this object (as if it's above me), because my projection is perspective.

I want to move this object in the center of clear area and see like it's in front of me without any distortion. How can I achieve that?

enter image description here

I see 2 solutions. 1) Draw my object offscreen in texture and after that draw this texture on screen in required position. 2) create scnView a bit taller. For example set frame size to = (0, (bottomHeight - topHeight) / 2, width, height + (bottomHeight - topHeight) / 2) to move the center of scnView in required position.

But I don't like first solution due to addition draw call and second solution even sounds crappy.

P.S. sorry for that pictures

Update: Basically I want to use perspective projection and move 3D object like a 2D image in SceneKit.

Joker
  • 263
  • 2
  • 16

3 Answers3

1

Sorry if I'm not be understanding correctly, but can you strafe camera up and center it, or will that not be clear enough?

func strafeY(vAmount: XFloat)
{
  nPosition = cgVecAdd(v1: nPosition, v2: cgVecScalarMult(v: nTarget, s: vAmount))
}
Voltan
  • 1,170
  • 1
  • 7
  • 16
  • I don't quite understand what is your suggestion. Currently I have a camera which pointed to the object. For example it in the center of view. I want to place this object in the top part of view but without any distortion. In other words: I want to create 2 types of moving for my object: 1) Standard with 1 finger, like in 3d (when I move the object down I see top surface of the object) 2) Another with 2 fingers, like in 2d (when I move this object down I see the same image). – Joker May 08 '18 at 08:21
  • Ok - once you move things in 3D (Scenekit), as you can see - things will change. One option is to have the 2D object behave like a bill board. Set a SCNLookAtConstraint on your object and always point it towards the camera. That should help some, but I don't think the end result will be what you want. If it's really needs to behave like a 2D object, then you can run SpriteKit over the top of Scenekit with an overlay. It can move left,right,top,and bottom and the perspective wouldn't change. – Voltan May 09 '18 at 18:12
  • Yes, but I want booth behaviors for the same object. For example I have an object in the center. I want to move it up on 100px like an image and after that rotate it like a 3D model in the new place. – Joker May 29 '18 at 19:58
1

Try this... generate a new scenekit game project, then replace the default rotation with the code below.

Rotate X slightly as you move the object up to to "somewhat" maintain the relationship to the eye.

You could create a similar but separate routine to do smaller increments to smooth it out.

    ship.runAction(SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-90)), y: 0, z: 0, duration: 0))

    let vRotateAmount: Float = 3

    let vAction1 =  SCNAction.move(to: SCNVector3Make(0, 1, 0), duration: 1)
    let vAction1a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(vRotateAmount)), y:0, z:0, duration: 1)

    let vAction2 = SCNAction.move(to: SCNVector3Make(0, 2, 0), duration: 1)
    let vAction2a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(vRotateAmount)), y:0, z:0,  duration: 1)

    let vAction3 =  SCNAction.move(to: SCNVector3Make(0, 1, 0), duration: 1)
    let vAction3a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-vRotateAmount)), y:0, z:0,  duration: 1)

    let vAction4 = SCNAction.move(to: SCNVector3Make(0, 0, 0), duration: 1)
    let vAction4a = SCNAction.rotateBy(x: CGFloat(GLKMathDegreesToRadians(-vRotateAmount)), y:0, z:0,  duration: 1)

    let seq = SCNAction.sequence([vAction1, vAction1a, vAction2, vAction2a, vAction3, vAction3a, vAction4, vAction4a])
    let allSeq = SCNAction.repeatForever(seq)
    ship.runAction(allSeq)
Voltan
  • 1,170
  • 1
  • 7
  • 16
0

Solved it by changing camera projectionTransform. Smth like:

let newMatrix = SCNMatrix4Mult(initialProjectionCameraMatrix, translationMatrix)
Joker
  • 263
  • 2
  • 16