I have a sprite object in XNA.
It has a size, position and rotation.
How to translate a point from the screen coordinates to the sprite coordinates ?
Thanks,
SW
You need to calculate the transform matrix for your sprite, invert that (so the transform now goes from world space -> local space) and transform the mouse position by the inverted matrix.
Matrix transform = Matrix.CreateScale(scale) * Matrix.CreateRotationZ(rotation) * Matrix.CreateTranslation(translation);
Matrix inverseTransform = Matrix.Invert(transform);
Vector3 transformedMousePosition = Vector3.Transform(mousePosition, inverseTransform);
You might find the following XNA picking sample useful:
http://creators.xna.com/en-us/sample/picking
One solution is to hit test against the sprite's original, unrotated bounding box.
So given the 2D screen vector (x,y):
translate the 2D vector into local sprite space: (x,y) - (spritex,spritey)
apply inverse sprite rotation
perform hit testing against bounding box
The hit test can of course be made more accurate by taking into account the sprite shape.
I think it may be as simple as using the Contains method on Rectangle, the rectangle being the bounding box of your sprite. I've implemented drag-and-drop this way in XNA; I believe Contains tests based on x and y being screen coordinates.
Related
I store my 3D points (many points) in a TGLPoints object. There is no other object in the scene than points. When drawing the points, I would like to fit them to the screen so they do not look far away or too close. I tried TGLCamera.ZoomAll but with no success and also the solution given here which adjusts the camera location, depth of view and scene scale:
objSize:=YourCamera.TargetObject.BoundingSphereRadius;
if objSize>0 then begin
if objSize<1 then begin
GLCamera.SceneScale:=1/objSize;
objSize:=1;
end else GLCamera.SceneScale:=1;
GLCamera.AdjustDistanceToTarget(objSize*0.27);
GLCamera.DepthOfView:=1.5*GLCamera.DistanceToTarget+2*objSize;
end;
The points did not appear on the screen this time.
What should I do to fit the 3D points to screen?
For each point build the scale factor by taking length of vector from points position to camera position. Then using this scale build your transformation matrix that you will apply to camera matrix. If scale is large that means point is farther you will apply reverse translation to bring that point in close proximity. I hope this is clear. To compute translation vector use following formula
translation vector = translation vector +/- (abs(scale)/2)
+/- will be decided by the scale magnitude if it is too far from camera you chose - in above equation.
I have been wondering for a while about how the transform matrix in spriteBatch is implemented. I've created a 2D camera, and the transform matrix is as follows:
if (needUpdate)
transformMatrix =
Matrix.CreateTranslation(-Position.X, -Position.Y, 0) *
Matrix.CreateScale(curZoom, curZoom, 1) ; needUpdate = false;
The camera works as good as I want, but I just want to know how the transformation is applied: Does the transformation only affects the axis of the sprites, or the screen co-ordinates too?
Thanks in advance!
I see you've answered your own question, but to provide complete information - SpriteBatch provides a similar interface to the traditional world-view-projection system of transformations.
The SpriteBatch class has an implicit projection matrix that takes coordinates in the "client space" of the viewport ((0,0) at the top left, one unit per pixel) and puts them on screen.
The Begin call has an overload that accepts a transformation matrix, which is the equivalent of a view matrix used for moving the camera around.
And the Draw call, while not actually using a matrix, allows you to specify position, rotation, scale, etc - equivalent to a world matrix used for positioning a model in the scene (model space to world space).
So you start with your "model" equivalent - which for SpriteBatch is a quad (sprite) of the size of the texture (or source rectangle). When drawn, that quad is transformed to its world coordinates, then that is transformed to its view coordinates, and then finally that is transformed to its projection coordinates.
I have an image where the user selects an arbitrary 4-cornered polygon.
I want to stretch this polygon into the entire image.
I've tried doing it with homography and cvWarpPerspective,
but the result was a Perspective transformation, which is not what I want.
Any ideas how to do this with OpenCV/EMGU ?
Thanks,
SW
What you're trying should work. Calculate the homography by making the 4 corners of the polygon correspond to (0,0) (0,height) (width,0) and (width,height).
Have a look at GetPerspectiveTransform
I think what you want is a reversal of perspective transform.
Here is what you must consider doing. Assume that you had the polygon at locations (x1,y1)....(x4,y4) originally on your screen (0,0) ....(w,h).
Applying perspective transform using cvWarpPerspective/getPerspectiveTransform you would be able to get the original co-ordinates to the known co-ordinates. So you should basically multiply the known co-ordinates with the inverse of the perspective transform matrix (unless that is non-invertible, in which case you must add a delta term to the homogeneous -coordinate term )
I'm using XNA but it doesn't matter too much for this example. So let's say I have a sprite. I then apply a scaling matrix before anything. Is the scaling matrix applied scaling the local axis of the sprite or just moving the points down? In other words, is applying a scaling matrix of 0.5f in the world space to my sprite at the world origin scaling down the local axis of the sprite or just all the points that make up that sprite by half?
The same kind of applies to a translation and then scaling. In my head, I picture a translation matrix of 30,30 as moving the sprite's local origin to 30,30 and as a result, the sprite's local axis to 30,30. Then, scaling by 0.5f would scale back the local axis but I don't see why the origin of the sprite would now be at 15,15.
This confusion compounds the fact that is you perform a translation of 1 to the right on the x-axis in the world, you are now moving based on the scale which you applied (so you would only move .5 in the world). This leads me to believe that the scale is applied to the object's own axis.
Btw, if you guys talk about the origin in your followups, could you state which origin you are referring to?
Thanks
Normally a sprite is defined by it's vertices (points). Applying a scaling matrix to a sprite will transform the vertices (points) of the sprite.
A scale matrix always assumes (0, 0) is the origin of the scale transform. So if you scale a sprite centered at (30, 30) all points will stretch away from the (0, 0) point. If it helps, imagine the sprite as a small dot on a circle around the (0, 0) point with that entire circle being scaled.
If you want to scale a sprite at (30, 30) from the center of the sprite, you have to translate the center of the sprite to (0, 0) first, then translate the sprite back out to (30, 30) after the scale has been performed.
So that would be:
Translate(-30, -30)
Scale(0.5)
Translate(30, 30)
To expand on Empyrean's answer, 3D worlds usually have at least four coordinate systems, each with its own local origin:
Object Space
World Space
Camera Space
View Space (2D!)
with three transformations:
Object to World
World to Camera
Camera to View
You can create new coordinate systems, for example 'Model Space', with the transformation 'Model to Object'. Using this, you get a series of steps:
Model -> scale -> Object
Object -> rotate -> translate -> World
World -> rotate -> translate -> Camera
Camera -> perspective -> View
In OpenGL you would push the matrices in the reverse order listed above, so the Model->Object transformation is the last to be pushed, and OpenGL should render the object correctly. I would assume XNA / DirectX has a similar system.
Getting more complex, Model Space can have a hierarchy of translations, scales and rotations in a tree to produce a skeletal system which can then be used to deform the model mesh. This is usually called Skinning.
So, to answer the question, depending on which transformation you apply a rotation transformation, for example, you will get different results. In the Model->Object transformation, the model will rotate about the object's origin. In the Object->World transformation, the object will rotate about the world's origin.
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.