This is my function to get the tile based upon mouse pos. As I said it’s my first game (and first java project) so the gurus on this forum will probably find 237 things that could be improved
Main thing for me at the moment is that it works and is quick enough to not limit the framerate.
//Get the tile in the 3D space where the passed 2D applet position resides
private Point3D getSquare(final Point2D point2D) {
if (point2D == null) {
return null;
}
final Polygon quad = new Polygon();
final Point3D realPos = new Point3D(0, 0, 0);
final Point2D currentPos = new Point2D(0, 0);
Point3D[] corners3D = null;
final Point2D[] corners2D = new Point2D[4];
final java.awt.geom.Point2D awtPoint2D = new java.awt.geom.Point2D.Float(0, 0);
corners2D[0] = new Point2D(0, 0);
corners2D[1] = new Point2D(0, 0);
corners2D[2] = new Point2D(0, 0);
corners2D[3] = new Point2D(0, 0);
final LinkedList<Point2D> cornersChecked = new LinkedList<Point2D>();
Math3D.generateArrays();
for (float i = LandTileFunctions.getMaxHeight(); i >= 0; i--) {
Math3D.getPoint3DfromPoint2D(point2D, i, realPos);
for (int j = -1; j < 2; j++) {
for (int k = -1; k < 2; k++) {
currentPos.setLocation(MyMath.floor(realPos.getX() + j), MyMath.floor(realPos.getY() + k));
if (!cornersChecked.contains(currentPos)) {
cornersChecked.add(currentPos.clone());
corners3D = LandTileFunctions.getTileInformation(currentPos); //Get the 3D points of all corners of the passed tile
if (corners3D != null) {
for (int l = 0; l < 4; l++) {
Math3D.getPoint2DfromPoint3D(corners3D[l], corners2D[l]);
quad.addPoint((int)corners2D[l].getX(), (int)corners2D[l].getY());
}
awtPoint2D.setLocation(point2D.getX(), point2D.getY());
if (quad.contains(awtPoint2D)) {
return corners3D[0];
} else {
quad.reset();
}
}
}
}
}
}
return null;
}
The used functions in the Math3D class looks like this:
private static FloatBuffer modelview = BufferUtils.createFloatBuffer(16); //The model view for caching
private static FloatBuffer projection = BufferUtils.createFloatBuffer(16); //The projection for caching
private static IntBuffer viewport = BufferUtils.createIntBuffer(16); //The view port for caching
//Generate the private variables before calling the below functions that rely on them
public static void generateArrays() {
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);
GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projection);
GL11.glGetInteger(GL11.GL_VIEWPORT, viewport);
modelview.rewind();
projection.rewind();
viewport.rewind();
}
//Get the position inside the application from a passed position on the applet together with depth
public static void getPoint3DfromPoint2D(Point2D p, float zPos, Point3D realPos) {
if (p == null) {
return;
}
final FloatBuffer windowCoordsF = FloatBuffer.allocate(3);
final float[] vec = new float[3];
//Get the coordinates at the far plane
GLU.gluUnProject(p.getX(), p.getY(), 1f, modelview, projection, viewport, windowCoordsF);
//Get the vector that goes from the UnProject to the camera
vec[0] = Camera.getX() - windowCoordsF.get(0);
vec[1] = Camera.getY() - windowCoordsF.get(1);
vec[2] = Camera.getZ() - windowCoordsF.get(2);
//Calculate X and Y based on a known Z
windowCoordsF.put(0, (zPos - windowCoordsF.get(2)) / vec[2] * vec[0] + windowCoordsF.get(0));
windowCoordsF.put(1, (zPos - windowCoordsF.get(2)) / vec[2] * vec[1] + windowCoordsF.get(1));
windowCoordsF.put(2, zPos);
realPos.setLocation(windowCoordsF.get(0), windowCoordsF.get(1), windowCoordsF.get(2));
}
//Get the position on the applet from a passed position inside the application
public static void getPoint2DfromPoint3D(Point3D p, Point2D AppletPos) {
if (p == null) {
return;
}
final FloatBuffer windowCoords = FloatBuffer.allocate(3);
//Get the coordinates at the screen
GLU.gluProject(p.getX(), p.getY(), p.getZ(), modelview, projection, viewport, windowCoords);
AppletPos.setLocation(windowCoords.get(0), windowCoords.get(1));
}
Be aware that if you walk down this route you’ll only be able to select the tiles, while if you implement picking you’ll be able to use it for small details on the screen as well.