Problem with Scale matrix in canvas scene and mouse position [WinForms] - c#

After applying a scale matrix to my scene of drawable objects, the actual position in the mouse cursor scene is incorrect.
In my opinion the problem is caused by the location gave me from the event of control (mousedown,up,and move) that is not faithful to my scene geometry.
var matrix = this.Control.Scene.Matrix.Inverse();
this.CoordsLabel.Text = matrix.MultiplyPoint(e.Location).ToString()
When i m very zoommed in my scene, "matrix.MultiplyPoint(e.Location)" return the same value for a short mouse movement. The other operation like translation, rotation works fine.
Example Image:
Here, The cursor is perfectly adjacent to the gray cross drawn
Here, This is very zoom situation, the cursor is not over the gray cross line, and for small mouse movement the gray line not change, as if the multiplication with scene matrix give me the same value of coord. (matrix.MultiplyPoint(e.Location))
Please hel me with this problem.
Thanks a lot.

Related

Why texture appear on Bottom Left with Frame Buffer Object

I'm trying to render to texture using FBO using OpenTK in C#.
When I try to render, everything show up and just fine except the texture is shown on bottom-left corner, I'm expecting it shown on the top left corner.
Also the Texture appear flipped in Y axis, So I need to modify the Texture Matrix after binding the Texture Target.
If I just bind my texture and draw the vertices, the sprite will appear on top-left corner.
The codes I use is looks exactly same from the official documentation.
I got 2 questions:
1. Am I doing it right to make the target texture show up properly by modifying the Texture Matrix?
2. How to make the texture target appear on top left corner?
Thanks in advance!
Actually Origin is at Bottom Left , therefore the FBO is getting displayed in the Bottom Left.
In the normal images , the texture space 0,0 is at top therefore you don't see it flipped.
So you have to add the texture matrix to make the space same.
When I try to render, everything show up and just fine except the texture is shown on bottom-left corner,
Yes. In OpenGL the origin (0,0) of 2D images (the viewport, textures, render buffers) is in the lower left.
I'm expecting it shown on the top left corner.
Why? The origin (as far as OpenGL is concerned) is in the lower left. Why'd you expect it in the top?
I encountered similar problems when the first time I tried FBO, so here my answer:
Although there several ways to workaround against this Upside down problem, Modifying Texture Matrix isn't bad idea at all. Sometimes modifying Texture matrix could be handy in certain situation, e.g: Use non normalized texture coordinate, So you can add such features to your bind texture function.
It's seems projection / viewport issue, if you are sure that the normal sprite appear on top-left coordinate, try to re-setup your projection / view / camera before unbind the FBO handle.

How to convert the bounds of a box to screen coordinates

I have a 2D unity project.
I cannot depend on OnMouseExit because overlapping 2D box colliders cause the method to trigger even when the mouse is inside the bounds, since something else is in front (which is not my intention).
I was going to manually check for the mouse exiting on every frame by using:
if(!_collider.bounds.contains(Input.MousePosition))
But this does not work because `mouse position' is in terms of the number of pixels across the screen, and 'bounds' is in terms of "units" relative to the origin of the scene. The camera is Orthographic and slides around to look at the 2D plane that the world's sprites sit on. I have no idea how many "units" fit across the screen and suspect that it would change as soon as you change the aspect ratio or screen size.
You can use ScreenToWorldPoint(), to convert from screen point to 3D/2D point based on the camera's viewport, something like this:
if(!_collider.bounds.contains(Camera.main.ScreenToWorldPoint(Input.MousePosition)))

Discontinuity in RaycastHit.textureCoord values (getting coordinates on texture right)

Hi I'm trying to get a particular coordinate on texture (under mouse cursor). So on mouse event I'm performing:
Ray outRay = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit clickRayHit = new RaycastHit();
if (!Physics.Raycast(outRay, out clickRayHit))
{
return;
}
Vector2 textureCoordinate = clickRayHit.textureCoord;
Texture2D objectTexture = gameObject.GetComponent<Renderer>().material.mainTexture as Texture2D;
int xCord = (int)(objectTexture.width * textureCoordinate.x);
int yCord = (int)(objectTexture.height * textureCoordinate.y);
But the problem is that the coordinate I'm getting is not preciesly under the cursor but "somewhat near it". And it's not like coordinates are consistently shifted in one way but shifting is not random as well. They are shifted differently in different points of the texture but:
they remain somwhere in the area of real cursor
and coordinates shifted in the same way when cursor is above the same point.
Here is part of coordinates log: http://pastebin.ca/3029357
If i haven't described problem good enough I can record a short screencast.
GameObject is a Plane.
If it is relevant mouseEvent is generated by windows mouseHook. (Application specific thing)
What am I doing wrong?
UPD: I've decided to record screencast - https://youtu.be/LC71dAr_tCM?t=42. Here you can see Paint window image through my application. On the bottom left corner you can see that Paint is displaying coordinates of the mouse (I'm getting this coordinates in a way I've described earlier - location of a point on a texture). So as I move mouse cursor you can see how coordinates are changing.
UPD2:
I just want to emphasize one more time that this shift is not constant or linear. There could be "jumps" around the mouse coordinates (but not only jumps). The video above explains it better.
So it was scaling problem after all. One of the scale values were negative and was causing this behaviour.

ILNumerics zoom selection rectangle and accessing the plotted data in ILPlotcube

I plot a surface in a Plot Cube with TwoDMode = true, when I try to zoom using the mouse left drag, the selection zoom rectangle goes behind the surface, therefore, it is not properly shown. Is it possible to force the selection rectangle to be on top of the surface? Moreover, is it possible by hovering or clicking the mouse on the surface, the X, Y and Z values be shown in some textboxes? Thank you very much.
Surfaces are inherently 3D objects. By default, they are intended to be used with ILPlotCube.TwoDMode set to false. But you can try to access the selection rectangle object and modify it accordingly. Try starting with plotCube.ZoomRectangle.Lines.Positions by raising its Z coordinate in order to move it closer to the camera.
Archieving the point of the surface under the cursor is not easy - but doable. Keep in mind, only the vertices of the surface tiles are known explicitly. You can use picking and the mouse events to get informed, if the mouse is over the surface:
surface.MouseMove += (_s,_a) => { yourHandler(_a); }
Afterwards, you are on your own. First, you will have to find the actual surface 3D coordinates. If you can be sure that the surface has not been rotated, you can take a look here.
The method in that thread gives you the surface X and Y coordinates. You can go further and (manually) find the corresponding tile for that position. For the final and exact X,Y,Z coordinates, you would have to interpolate the tile (triangle) vertices to the actual mouse position, using barycentric interpolation.
In order to show the 3D coordinate, you can simply use an ILLabel. You may or may not want to put that into an ILScreenObject.

Casting a ray from mouse through distortion matrix

I've searched the board, as well as the oculus board, and unity board. Couldn't really find something that helped.
I'm working on a vehicle simulation. Before we started using the oculus, it was just a regular first person perspective. You used a racing wheel/pedals to drive and the mouse to control all the buttons and switches etc. We use raycasting from the mouse point on the screen into the world to interact with the various controls in the vehicle.
Now that we're using the oculus, the raycast isn't taking into account the distortion matrix used on the oculus cameras. So you're not actually casting a ray at what you're visually clicking on. Using Debug.DrawRay I found that it was slightly off. Just to be sure, I disabled the lens correction via inspector on the OVRCameraController and sure enough the raycasting was working again.
The ray itself is calculated the usual way one does when firing from the mouse point:
ScreenPointToRay(Input.mousePosition);
Would anyone have any idea how I can adjust my ray so it works with lens correction on?
Cheers,
Gordon
Simply multiply the Distortion-Matrix with the Ray's Vectors (Position and Normal) and you have your new Ray. I would suggest using Homogeneous Coordinates with 4x4 Matrix and Vec4's where Positions has component w = 1.0 and Normals have w = 0.0; This way you can simply multiply and you are done - depending on lookup direction you might have to use the inverse matrix :)
Alright, what I ended up doing was creating a 3D cursor, bypassing the distortion matrix entirely.
I placed a gameobject at the same place as the "head" (between left eye and right eye cameras). It has a script on it that rotates up/down/left/right based on mouse movement. I then temporarily put a spot light with a narrow cone and high intensity on it so it looked like a laser pointer. I figured if the light is hitting things, so should a raycast of the same origin. Which ended up working.
However this didn't really solve the issue of using a cursor. I tried a number of things that ultimately didn't work (didn't line up with with where the light/raycast hit).
Finally I realized I was overlooking something very simple. I lowered the near clipping plane of the cameras and placed a plane as close as I could to the camera while still being visible. I then rotated it on local y by 180 so it would be invisible to the cameras and not block ray casts.
I then added some code so that when a raycast hit something, it would fire a second raycast from the hit point back to the origin. On the way it would have to hit the plane, which was essentially at the near clipping plane. I would then move my 3D cursor to that hit point.
Now it works as intended. Where the cursor is, is where the original raycast hit. The cursor now matched the position of the laser dot. So then I removed the light component. Done.
Hope this helps someone else someday.

Categories

Resources