Rotate and zoom entire 2d scene - xna

I'm currently working on a Final Fantasy like game, and I'm at the point where I'm working on the effect when switching from world map to battles. I wanted a zoom-in while rotating effect, I was thinking of simply animating a transformation matrix that would be passed to SpriteBatch.Begin, but my problem is when I rotate, the rotation origin is the top left of my entire scene and it doesn't "zoom-in" centered. I saw that you could specify a rotation origin on SpriteBatch.Draw but that sets it per sprites and I want to rotate the entire scene.

The transform you are looking for is this:
Matrix Transform = Matrix.CreateTranslation(-Position)
* Matrix.CreateScale(scale)
* Matrix.CreateRotationZ(angle)
* Matrix.CreateTranslation(GraphisDevice.Viewport.Bounds.Center);

Related

scaling issue when projecting uiview in front of scenekit camera

content
first i have a 360 (equirectangular) image viewer by applying the image as a texture onto a sphere with the scenekit camera at the center.
then i enter a "drawing mode" where i can use my finger to draw on a transparent UIView
when i'm done, i take the drawing and apply it to my sphere as an annotation
problem (with video example)
the problem is in this 3rd step, the scale isn't saved correctly.
https://www.dropbox.com/s/a2l3vvx92sa3cgh/drawing_defect_trimmed_480p.mp4?dl=0
temporary solution
i was able to add a magic number to the expected scale which lessens the scaling problem, but it is still a little bit off and obviously suboptimal from a technical perspective.
e.g. “scale_used = expected_scale + magic_constant”
implementation details
I am projecting a UIView in front of a Scene Kit camera at some custom
distance in the Scene Kit world and trying to make it so the new
Scene Kit node will have exactly the same visual size.
the approach is to calculate the perspective projection of the item,
located in the world at drawingContentItem.distance using camera
zNear - “(screenHeight * distance / Float(zNear))”.
Then we assume that size of visible world of scene kit is from -1000
to 1000; and the view angle is 60 degrees; and calculate the ratio of
scene Kit near plane view to UIView - “(sceneScreenHeight /
nearPlaneHeightInWorlCoordinates)”.
that gives us the finalHeight of drawing in the world coordinates and
we use this to calculate the scale.
But it seems that there is some mistake in the formula and it causes
the need for the magical number. :(

SceneKit - displaying 2d view inside scene at (x, y, z)

I need to display some view with notification in my scene at given position. This notification should stay the same size, no matter what is the distance. But most important is that it should look like 2d object, no matter what rotation camera has. I don't know if I can actually insert some 2d object, this would be great. So far I'm experimenting with SCNNodes containing Box. I don't know how to make them always rotate towards camera (which rotates in every axis). I tried to use
let lookAt = SCNLookAtConstraint(target: self.cameraNode)
lookAt.gimbalLockEnabled = true
notificationNode.constraints = [lookAt]
This almost works, but nodes are all rotated in some random angle. Looks like UIView with rotation applied. Can someone help me with this?
Put your 2-D object(s) on an SCNPlane. Make the plane node a child of your camera node. Position and rotate the plane as you like, then leave it alone. Anytime the camera moves or rotates, the plane will move and revolve with it always appearing the same.
Ok I know how to do it now. Create empty node without geometry, and add a new node with SCNLookAtConstraint. Then I can move this invisible node with animation, and subnode stays looking at camera.

Rotate 3D cube so side is facing user

How do I figure out the new angle and rotation vectors for the most visible side of the cube?
Why: The user can rotate cube, but when finished I'd like the cube to snap to a side facing the user.
What: I'm currently using CoreAnimation in iOS to do the rotation with CATransform3D. I have the current angle and the rotation vectors so I can do this:
CATransform3DMakeRotation(angle, rotationVector[0], rotationVector[1], rotationVector[2]);
Additional Info: I'm currently using Bill Dudney's Trackball code to generate movement and calculate angle and rotation vector.
Your camera's lookAt vector - probably {0, 0, 1} - determines what side is closer to user.
You need to create normal for every side of the cube. Then rotate them in same way as cube. After that, calculate the angle between every normal vector and the camera lookAt vector using a dot product. Whichever normal has the largest dot product is the side closest to the camera.

What's the correct way to set up a landscape orthographic projection using OpenGL-ES 2.0 on iOS?

This is all in OpenGL ES 2.0...
I'm trying to mix a 3D perspective projection with a 2D orthographic projection so I can have a HUD sat on top of the 3D scene in my game.
The game runs with a landscape orientation, and I'm getting really confused how to handle device orientations.
I am rendering the 3D stuff with a suitable projection matrix, and am rotating the modelView matrix and my lighting by 90 degrees so the 3D scene is the right way up. This bit all works fine.
My problem is I can't work out how to set up the 2D projection matrix properly so the origin is in the upper left corner when the device is in landscape with the home button on the left.
How do I correctly construct the orthographic matrix so this happens? I am currently using this
// OrthoMatrix does the same as the old GLOrthof function (left, right, bottom, top, near, far);
projectionMatrix2D = mat4::OrthoMatrix(0, screenWidth, screenHeight , 0, -1.0, 1.0);
However this just puts the origin in the top left if the device is in portrait with the home button at the bottom, and rotating the device in my hand means everything is on its side.
Should I be trying to alter the 2D projection matrix or is there something else I need to be doing?
I asked this on Gamedev, but in a more general way and received a helpful answer.
How can I create an orthographic display that handles different screen dimensions?

What is this rotation behavior in XNA?

I am just starting out in XNA and have a question about rotation. When you multiply a vector by a rotation matrix in XNA, it goes counter-clockwise. This I understand.
However, let me give you an example of what I don't get. Let's say I load a random art asset into the pipeline. I then create some variable to increment every frame by 2 radians when the update method runs(testRot += 0.034906585f). The main thing of my confusion is, the asset rotates clockwise in this screen space. This confuses me as a rotation matrix will rotate a vector counter-clockwise.
One other thing, when I specify where my position vector is, as well as my origin, I understand that I am rotating about the origin. Am I to assume that there are perpendicular axis passing through this asset's origin as well? If so, where does rotation start from? In other words, am I starting rotation from the top of the Y-axis or the x-axis?
The XNA SpriteBatch works in Client Space. Where "up" is Y-, not Y+ (as in Cartesian space, projection space, and what most people usually select for their world space). This makes the rotation appear as clockwise (not counter-clockwise as it would in Cartesian space). The actual coordinates the rotation is producing are the same.
Rotations are relative, so they don't really "start" from any specified position.
If you are using maths functions like sin or cos or atan2, then absolute angles always start from the X+ axis as zero radians, and the positive rotation direction rotates towards Y+.
The order of operations of SpriteBatch looks something like this:
Sprite starts as a quad with the top-left corner at (0,0), its size being the same as its texture size (or SourceRectangle).
Translate the sprite back by its origin (thus placing its origin at (0,0)).
Scale the sprite
Rotate the sprite
Translate the sprite by its position
Apply the matrix from SpriteBatch.Begin
This places the sprite in Client Space.
Finally a matrix is applied to each batch to transform that Client Space into the Projection Space used by the GPU. (Projection space is from (-1,-1) at the bottom left of the viewport, to (1,1) in the top right.)
Since you are new to XNA, allow me to introduce a library that will greatly help you out while you learn. It is called XNA Debug Terminal and is an open source project that allows you to run arbitrary code during runtime. So you can see if your variables have the value you expect. All this happens in a terminal display on top of your game and without pausing your game. It can be downloaded at http://www.protohacks.net/xna_debug_terminal
It is free and very easy to setup so you really have nothing to lose.

Resources