00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010 #include "vgui_back_project.h"
00011 #include <vgui/vgui_gl.h>
00012 #include "vgui_transpose_4x4.h"
00013 #include "vgui_multiply_4x4.h"
00014
00015 static
00016 void fast_null(double const P0[4],
00017 double const P1[4],
00018 double const P2[4],
00019 double f[4])
00020 {
00021 f[0] = -P0[1]*P1[2]*P2[3]+P0[1]*P1[3]*P2[2]+P1[1]*P0[2]*P2[3]-P1[1]*P0[3]*P2[2]-P2[1]*P0[2]*P1[3]+P2[1]*P0[3]*P1[2];
00022 f[1] = P0[0]*P1[2]*P2[3]-P0[0]*P1[3]*P2[2]-P1[0]*P0[2]*P2[3]+P1[0]*P0[3]*P2[2]+P2[0]*P0[2]*P1[3]-P2[0]*P0[3]*P1[2];
00023 f[2] = -P0[0]*P1[1]*P2[3]+P0[0]*P1[3]*P2[1]+P1[0]*P0[1]*P2[3]-P1[0]*P0[3]*P2[1]-P2[0]*P0[1]*P1[3]+P2[0]*P0[3]*P1[1];
00024 f[3] = P0[0]*P1[1]*P2[2]-P0[0]*P1[2]*P2[1]-P1[0]*P0[1]*P2[2]+P1[0]*P0[2]*P2[1]+P2[0]*P0[1]*P1[2]-P2[0]*P0[2]*P1[1];
00025 }
00026
00027 bool vgui_back_project_d3d4d4d4d4_d4(double const x[3],
00028 double const P0[4],
00029 double const P1[4],
00030 double const P2[4],
00031 double const pi[4],
00032 double X[4])
00033 {
00034
00035
00036 double f0[4]; fast_null(P1, P2, pi, f0);
00037 double f1[4]; fast_null(P2, P0, pi, f1);
00038 double f2[4]; fast_null(P0, P1, pi, f2);
00039 for (unsigned i=0; i<4; ++i)
00040 X[i] = x[0]*f0[i] + x[1]*f1[i] + x[2]*f2[i];
00041 return true;
00042 }
00043
00044 bool vgui_back_project_d3d4_d4(double const x[3], double const pi[4], double X[4])
00045 {
00046 double P[4][4]; glGetDoublev(GL_PROJECTION_MATRIX, &P[0][0]); vgui_transpose_4x4(P);
00047 double M[4][4]; glGetDoublev(GL_MODELVIEW_MATRIX, &M[0][0]); vgui_transpose_4x4(M);
00048 double T[4][4]; vgui_multiply_4x4(P, M, T);
00049 return vgui_back_project_d3d4d4d4d4_d4(x, T[0], T[1], T[3], pi, X);
00050 }
00051
00052 bool vgui_back_project_iid4_d4(int vx, int vy, double const pi[4], double X[4])
00053 {
00054 GLint vp[4];
00055 glGetIntegerv(GL_VIEWPORT, vp);
00056 double x[3] = { 2*(vx-vp[0])/double(vp[2])-1,
00057 2*(vy-vp[1])/double(vp[3])-1,
00058 1 };
00059 return vgui_back_project_d3d4_d4(x, pi, X);
00060 }
00061
00062 bool vgui_back_project_ii_dd(int vx, int vy, double *x, double *y)
00063 {
00064 double const pi[4] = { 0, 0, 1, 0 };
00065 double X[4];
00066 if (!vgui_back_project_iid4_d4(vx, vy, pi, X))
00067 return false;
00068 if (X[3] == 0)
00069 return false;
00070 if (x) *x = X[0]/X[3];
00071 if (y) *y = X[1]/X[3];
00072 return true;
00073 }