RTS like Mouse in an isometric view (LWJGL) - java

I really have an issue with mouseclicks in an isometric view.
Simply i have a flat map, and, like i said, a camera in an isometric view. Now when i click in the window i want to get the Coordinates where i clicked on the map. Any Help?

actually, i figured it out.
int winX = ... //the x coordinate of the Click, given Parameter
int winY = ... //the y Coordinate of the Click, given Parameter
FloatBuffer winZ = BufferUtils.createFloatBuffer(1); //the x coordinate of the click, will be calculated
FloatBuffer pos = BufferUtils.createFloatBuffer(3); // the final position of the click
FloatBuffer modelview = BufferUtils.createFloatBuffer(16);
FloatBuffer projection = BufferUtils.createFloatBuffer(16);
IntBuffer viewport = BufferUtils.createIntBuffer(16);
GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
GL11.glGetFloat(GL11.GL_PROJECTIONMATRIX, projection);
GL11.glReadPixels(winX, winY, 1,1, GL11._GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ) //calculate the Z Coordinate of the Click
GLU.gluUnProject((float)(winX), (float)(winY), (float)(winZ.get(0)), modelview, projection, viewport, pos); //Calculating the 3D Position of the click, saved in pos
Now since you have the 3D Coordinates you can do some simple vector calculation and collision detection to get the point you clicked on

Related

libgdx rotate 3d object following mouse

i try to rotate a 3D instance when I move the mouse. i use Orthographic Camera, and i have a tiled isomap in background.
[EDIT] I use this code :
public boolean mouseMoved (int x, int y) {
Vector3 direction = new Vector3();
Vector3 worldCoordinate = cam.unproject(new Vector3(x, y, 0));
direction = (worldCoordinate).sub(position).nor();
direction.set(-direction.x, -direction.y, -direction.z);
Matrix4 instanceRotation = instance.transform.cpy().mul(instance.transform);
instanceRotation.setToLookAt(direction, new Vector3(0,-1,0));
instanceRotation.rotate(0, 0, 1, 180);
quat = new Quaternion();
instanceRotation.getRotation(quat);
instance.transform.set(position, quat);
return false;
}
Now, the instance follows the cursor, but in all axes. I just want to turn on the Y axis. I can change quat.x = 0 and quat.z = 0 to lock the rotation. After that, the rotation only works on the Y axis. But, the model should turn over if my cursor is at the top of the screen, but it remains facing, no matter where my cursor is.
I don't know how to convert the coordinates to tell my rotation that it needs to turn over. And to modify the quat in this way is not very elegant
Edit : Some image for illustrate what i want
Here, with cursor in the bottom of the screen, the model turn to look in good direction :
Here, the model dont turn over, like the cursor is in bottom of the screen :

LibGDX mouse position in world deviation

I ve got some problem with mouse position in game world in LibGDX.
There is some difference between my mouse position in world and real position.
To get my mouse position Im using:
Vector3 mousePos = gamecam.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
speechBaloon.setPosition(mousePos.x, mousePos.y); //texture that follows cursor
where:
public static final int WIDTH = 1920;
public static final int HEIGHT = 1080;
gamecam = new OrthographicCamera();
gamePort = new FitViewport(MyGame.WIDTH, MyGame.HEIGHT, gamecam);
gamecam.setToOrtho(false, MyGame.WIDTH, MyGame.HEIGHT);
Here some photos(added mouse coursor by myself, cuz my screens program doesnt have options to capture photo with cursor, but scale between distance is preserved):
img1
img2 - full resolution
As u can see in img2 there is a difference between X position, and in img1 between Y. I cannot post more than 2 photos, but when I drag cursor to the center of Y axis in situation from img1, my texture and cursor are covering themselves.
I have resize function (my class implements Screen).
#Override
public void resize(int width, int height)
{
gamePort.update(width, height);
hudPort.update(width, height);
}
Thanks in advance for help!
Like Tenfour04 noticed as long as Viewport (gamePort) is used we need to call .unproject() on Viewport instance.
From documentation of LibGDX Camera:
Function to translate a point given in screen coordinates to world
space. ...
The viewport is assumed to span the whole screen and is fetched from
Graphics.getWidth() and Graphics.getHeight().
Final outcome:
Vector3 mousePos = gamePort.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
speechBaloon.setPosition(mousePos.x, mousePos.y); //texture that follows cursor

Libgdx + rotate sprite point to the touch position

I'm having problem trying to point my "arrow_sprite" to the touch position.
The result I want is that the arrow(the sprite that I want to rotate)will point to the touch position.
How can I acheive this?
You need to calculate the vector between the touch position and the sprite position. To do so you have to unproject the touch position received through your InputProcessor.
public class MyInputProcessor implements InputProcessor {
...
#Override
public boolean touchDown (int x, int y, int pointer, int button) {
Vector3 touchDown = new Vector3(x, y, 0);
camera.unproject(touchDown);
Vector3 spritePosition = new Vector3(yourSpriteX, yourSpriteY, 0);
spritePosition.sub(touchDown);
return false;
}
...
}
Now we have a vector pointing from your sprite to the touch position. From there you just need to calculate the rotation angle. One way would be to use Vector2.angle(), as such creating a Vector2 from the spritePosition Vector3.
If you want to draw in 2D, then you have to set your SpriteBatch to Camera.combined,
something like this : yourBatch.setProjectionMatrix(yourCamera.combined);
Then you must unproject the camera like "batch" said.
After, you must choose if you want to use a vector or 2d coordinate. Basically identycal ending for angle calculation :
First define a float degrees then make it like so in the touchDown method :
degrees = (float) ((Math.atan2 (touchPoint.x - arrowPosition.x, -(touchPoint.y - arrowPosition.y))*180.0d/Math.PI)+90.0f);
assuming you use a Vector3 or 2 for both input and arrow.
then when rendering the Arrow sprite :
Batch.draw(Arrow, x, y, originX, originY, width, height, scaleX, scaleY, degrees);
Hope this will be helpfull.
Just like Psilopat said, we define the degree by :
degrees = (float) ((Math.atan2 (touchPoint.x - arrowPosition.x, -(touchPoint.y - arrowPosition.y))*180.0d/Math.PI)+90.0f);
but if the rotation seems wrong, change the "+90.0f" at the end of line to something else. My arrow is pointing up, so I change it to "-180.0f"

Why doesn't gluUnProject() seem to behave?

I am trying to find the coordinates of my mouse on a flat 3D surface. After googling a bit on that, I found out that you use gluUnProject for doing so. So, I implemented that. Here is my code (when taking away the parts that are not interesting):
public class Input {
private FloatBuffer modelView = BufferUtils.createFloatBuffer(16);
private FloatBuffer projection = BufferUtils.createFloatBuffer(16);
private IntBuffer viewport = BufferUtils.createIntBuffer(16);
private FloatBuffer location = BufferUtils.createFloatBuffer(3);
private FloatBuffer winZ = BufferUtils.createFloatBuffer(1);
public float[] getMapCoords(int x, int y)
{
modelView.clear().rewind();
projection.clear().rewind();
viewport.clear().rewind();
location.clear().rewind();
winZ.clear().rewind();
glGetFloat(GL_MODELVIEW_MATRIX, modelView);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetInteger(GL_VIEWPORT, viewport);
float winX = (float)x;
float winY = (float)viewport.get(3) - (float)y;
glReadPixels(x, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, winZ);
gluUnProject(winX, winY, winZ.get(0), modelView, projection, viewport, location);
return new float[] {location.get(0), location.get(1), location.get(2)};
}
}
When I call this function, passing in the X and Y coordinates of the mouse, I get some numbers that increase by 100 for every pixel I move with my mouse (it should be around 1). After doing some prints from various variables, I found out that the winZ buffer contains the value 1.0. My gluPerspective is set up in such a way that its near clipping point it at 0.1 and its far point at 10000, which would explain why the number is increasing that rapidly. Yet I don't know how to force openGl to use my flat plane instead for finding this distance.
So now I am wondering; if this is the correct/best/easiest method for finding the mouse coordinates on a surface in the 3D world, what could I be doing wrong? If it is not, what is a better way of doing it?
Yes, this is the correct method to use. You are probably just calling it at the point where the matrices do not contain "good values" (might be caused by glPush/PopMatrix() functions in your code).
To confirm you are getting good coordinates, draw a single GL_POINT at the coordinates you get, after you get them (disable depth test and increase point size to, say, 10 pixels). If the point is moving under your mouse, then the calculated coords are correct but the matrices are not.

Getting object coordinates from camera

I've implemented a camera in Java using a position vector and three direction vectors so I can use gluLookAt(); moving around in `ghost mode' works fine enough, but I want to add collision detection. I can't seem to figure out how to transform my position vector to coordinates in which OpenGL draws my objects.
A rough sketch of my drawing loop is this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera.setView();
drawer.drawTheScene();
I'm at a loss of how to proceed; looking at the ModelView matrix between calls and my position vector, I haven't found any kind of correlation.
Finally figured it out by reviewing http://fly.cc.fer.hr/~unreal/theredbook/chapter03.html again. To get from eye space (camera) to object space, you have to multiply that vector with the inverse of the ModelView matrix, or in code:
Vector4f vpos = new Vector4f(0, 0, 0, 1);
// (0,0,0,1) because it's relative to the cam
float mv[]=new float[16];
ByteBuffer temp = ByteBuffer.allocateDirect(64);
temp.order(ByteOrder.nativeOrder());
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, (FloatBuffer)temp.asFloatBuffer());
temp.asFloatBuffer().get(mv);
Matrix4f m4 = new Matrix4f();
m4.load((FloatBuffer)temp.asFloatBuffer());
m4.invert();
vpos = Matrix4f.transform(m4, vpos, vpos);

Categories

Resources