core/vgui/internals/vgui_back_project.cxx
Go to the documentation of this file.
00001 // This is core/vgui/internals/vgui_back_project.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 // \brief  See vgui_back_project.h for a description of this file.
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   // X = ( (x[0] P1.P2 + x[1] P2.P0 + x[2] P0.P1).pi )*
00035   //             f0           f1           f2
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 }