/* * Moonlight|3D Copyright (C) 2005 The Moonlight|3D team * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Created on Nov 3, 2005 */ package ml.math; /** * \package ml.math * * This is a library of helper classes for mathematical functions. * Its use is preferred over potentially less thoroughly tested and * therefore potentially buggy home-grown code. * * This package is part of the core program. */ /** * This class contains some static helper functions for various common * mathematical tasks. * * @author gregor */ public class Helper { /** * Private constructor to prevent instantiation */ private Helper() { } /** * Helper class to return result tuple of frexp() */ public static class FRExpResult { /** * normalised mantissa */ public double mantissa; /** * exponent of floating point representation */ public int exponent; } /** * An implementation of the C standard library frexp() function. * * @param value the number to split * @return a touple of normalised mantissa and exponent */ public static FRExpResult frexp(double value) { int i = 0; if (value != 0.0) { int sign = 1; if (value < 0) { sign = -1; value = -value; } // slow... while (value < 0.5) { value = value*2.0; i = i-1; } while (value >= 1.0) { value = value*0.5; i = i+1; } value = value*sign; } FRExpResult result=new FRExpResult(); result.mantissa=value; result.exponent=i; return result; } /** * Project point from 3d world coordinates to screen coordinates. The input * is a point on the screen and the result is a point in screen space, where * the screen rectangle is in the range of -1.0 to 1.0 on both x and y axis. * The third component of the returned vector contains the depth of the point * in screen space. * * @param modelView the OpenGL modelview matrix * @param projection the OpenGL projection matrix * @param point the point to project on screen * @return the screen space coordinates scaled to -1.0 to 1.0 on both axes */ public static Vector3D project(Matrix4 modelView, Matrix4 projection, Vector3D point) { return projection.multiply(modelView.multiply(point)); } /** * A function similar to gluUnProject, but without need for a GLU interface. * It projects a ray from the current camera position through the projection * plane at the given view coordinate. * * @param modelView the GL modelview matrix * @param projection the GL projection matrix * @param x the x coordinate of the point on the projection plane, range -1.0 to 1.0 * @param y the y coordinate of the point on the projection plane, range -1.0 to 1.0 * @return a ray from the camera position throught the given point on the projection plane */ public static Ray unProject(Matrix4 modelView, Matrix4 projection, double x, double y) { Vector3D viewVector=new Vector3D(); Matrix4 unprojectMatrix=projection.multiply(modelView).invert(); viewVector.X1=x; viewVector.X2=y; viewVector.X3=-0.1; Vector3D directionVector=unprojectMatrix.multiply(viewVector); Matrix4 inverseModelViewMatrix=modelView.invert(); Vector3D positionVector=new Vector3D(); positionVector.X1=inverseModelViewMatrix.X[0][3]; positionVector.X2=inverseModelViewMatrix.X[1][3]; positionVector.X3=inverseModelViewMatrix.X[2][3]; Ray ray=new Ray(); ray.start=positionVector; ray.direction=directionVector.sub(ray.start); return ray; } /** * A convenience wrapper around unProject with double arguments. This variant * takes the screen coordinates in pixels as units and the width and height of * the screen in pixels as well. * * @param modelView the GL modelview matrix * @param projection the GL projection matrix * @param x the x coordinate of the point on the projection plane, range 0.0 to width * @param y the y coordinate of the point on the projection plane, range 0.0 to height * @param width the width of the projected area on screen * @param height the height of the projected area on screen * @return a ray from the camera position throught the given point on the projection plane */ public static Ray unProject(Matrix4 modelView, Matrix4 projection, int x, int y, int width, int height) { return unProject(modelView,projection,(2.0*x/(1.0*width))-1,(2.0*(height-y-1)/(1.0*height))-1); } }