package tk.amberide.engine.data.math.vec;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW_MATRIX;
import static org.lwjgl.opengl.GL11.GL_PROJECTION_MATRIX;
import static org.lwjgl.opengl.GL11.GL_VIEWPORT;
import static org.lwjgl.opengl.GL11.glGetFloat;
import static org.lwjgl.opengl.GL11.glGetInteger;
import static org.lwjgl.util.glu.GLU.gluUnProject;
/**
*
* @author Tudor
*/
public class Ray {
public Vec3d point;
public Vec3d dir;
public Ray(Vec3d point, Vec3d dir) {
this.point = point;
this.dir = dir;
}
public static Ray getRay(float cursorX, float cursorY) {
IntBuffer viewport = ByteBuffer.allocateDirect((Integer.SIZE / 8) * 16).order(ByteOrder.nativeOrder()).asIntBuffer();
FloatBuffer modelview = ByteBuffer.allocateDirect((Float.SIZE / 8) * 16).order(ByteOrder.nativeOrder()).asFloatBuffer();
FloatBuffer projection = ByteBuffer.allocateDirect((Float.SIZE / 8) * 16).order(ByteOrder.nativeOrder()).asFloatBuffer();
FloatBuffer pickingRayBuffer = ByteBuffer.allocateDirect((Float.SIZE / 8) * 3).order(ByteOrder.nativeOrder()).asFloatBuffer();
glGetFloat(GL_MODELVIEW_MATRIX, modelview);
glGetFloat(GL_PROJECTION_MATRIX, projection);
glGetInteger(GL_VIEWPORT, viewport);
float winX = (float) cursorX;
// convert window coordinates to opengl coordinates (top left to bottom left for (0,0)
float winY = (float) viewport.get(3) - (float) cursorY;
// now unproject this to get the vector in to the screen
// take the frustrm and unproject in to the screen
// frustrum has a near plane and a far plane
// first the near vector
gluUnProject(winX, winY, 0, modelview, projection, viewport, pickingRayBuffer);
Vec3d nearVector = new Vec3d(pickingRayBuffer.get(0), pickingRayBuffer.get(1), pickingRayBuffer.get(2));
pickingRayBuffer.rewind();
// now the far vector
gluUnProject(winX, winY, 1, modelview, projection, viewport, pickingRayBuffer);
Vec3d farVector = new Vec3d(pickingRayBuffer.get(0), pickingRayBuffer.get(1), pickingRayBuffer.get(2));
//save the results in a vector, far-near
return new Ray(nearVector, farVector.sub(nearVector));
}
}