core/vgui/internals/vgui_draw_line.cxx
Go to the documentation of this file.
00001 // This is core/vgui/internals/vgui_draw_line.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "vgui_draw_line.h"
00010 #include <vgui/vgui_gl.h>
00011 #include <vgui/internals/vgui_multiply_4x4.h>
00012 #include <vgui/internals/vgui_transpose_4x4.h>
00013 
00014 //--------------------------------------------------------------------------------
00015 
00016 #define dot4(a, b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
00017 #define l_c4(a, x, b, y, ax_plus_by) { for (int i=0; i<4; ++i) (ax_plus_by)[i] = (a)*(x)[i] + (b)*(y)[i]; }
00018 
00019 bool vgui_draw_line(double const T[4][4], double const X[4], double const Y[4])
00020 {
00021   double T0_X = dot4(T[0], X);
00022   double T1_X = dot4(T[1], X);
00023   double T3_X = dot4(T[3], X);
00024 
00025   double T0_Y = dot4(T[0], Y);
00026   double T1_Y = dot4(T[1], Y);
00027   double T3_Y = dot4(T[3], Y);
00028 
00029   double tmp[4];
00030   glBegin(GL_LINE_STRIP);
00031 
00032   // line x_dev = -w_dev :
00033   {
00034     double u = T0_X+T3_X;
00035     double v = T0_Y+T3_Y;
00036     double y_dev = (v*T1_X - u*T1_Y);
00037     double w_dev = (v*T3_X - u*T3_Y);
00038     if (!w_dev) { }
00039     else if ((w_dev>0) ? (-w_dev<=y_dev && y_dev<=w_dev) : (-w_dev>=y_dev && y_dev>=w_dev)) {
00040       l_c4(v, X, -u, Y, tmp);
00041       glVertex4dv(tmp);
00042     }
00043   }
00044 
00045   // line x_dev = +w_dev :
00046   {
00047     double u = T0_X-T3_X;
00048     double v = T0_Y-T3_Y;
00049     double y_dev = (v*T1_X - u*T1_Y);
00050     double w_dev = (v*T3_X - u*T3_Y);
00051     if (!w_dev) { }
00052     else if ((w_dev>0) ? (-w_dev<=y_dev && y_dev<=w_dev) : (-w_dev>=y_dev && y_dev>=w_dev)) {
00053       l_c4(v, X, -u, Y, tmp);
00054       glVertex4dv(tmp);
00055     }
00056   }
00057 
00058   // line y_dev = -w_dev :
00059   {
00060     double u = T1_X+T3_X;
00061     double v = T1_Y+T3_Y;
00062     double x_dev = (v*T0_X - u*T0_Y);
00063     double w_dev = (v*T3_X - u*T3_Y);
00064     if (!w_dev) { }
00065     else if ((w_dev>0) ? (-w_dev<=x_dev && x_dev<=w_dev) : (-w_dev>=x_dev && x_dev>=w_dev)) {
00066       l_c4(v, X, -u, Y, tmp);
00067       glVertex4dv(tmp);
00068     }
00069   }
00070 
00071   // line y_dev = +w_dev :
00072   {
00073     double u = T1_X-T3_X;
00074     double v = T1_Y-T3_Y;
00075     double x_dev = (v*T0_X - u*T0_Y);
00076     double w_dev = (v*T3_X - u*T3_Y);
00077     if (!w_dev) { }
00078     else if ((w_dev>0) ? (-w_dev<=x_dev && x_dev<=w_dev) : (-w_dev>=x_dev && x_dev>=w_dev)) {
00079       l_c4(v, X, -u, Y, tmp);
00080       glVertex4dv(tmp);
00081     }
00082   }
00083 
00084   glEnd();
00085   return true;
00086 }
00087 
00088 bool vgui_draw_line(double const P[4][4], double const M[4][4], double const X[4], double const Y[4])
00089 {
00090   double T[4][4];
00091   vgui_multiply_4x4(P, M, T);
00092   return vgui_draw_line(T, X, Y);
00093 }
00094 
00095 bool vgui_draw_line(double const X[4], double const Y[4])
00096 {
00097   double P[4][4]; glGetDoublev(GL_PROJECTION_MATRIX, &P[0][0]); vgui_transpose_4x4(P);
00098   double M[4][4]; glGetDoublev(GL_MODELVIEW_MATRIX,  &M[0][0]); vgui_transpose_4x4(M);
00099 
00100   double T[4][4];
00101   vgui_multiply_4x4(P, M, T);
00102   return vgui_draw_line(T, X, Y);
00103 }
00104 
00105 //--------------------------------------------------------------------------------
00106 
00107 #define dot3(a, b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2])
00108 #define cross3(a, b, c) { \
00109   (c)[0] = (a)[1]*(b)[2] - (a)[2]*(b)[1]; \
00110   (c)[1] = (a)[2]*(b)[0] - (a)[0]*(b)[2]; \
00111   (c)[2] = (a)[0]*(b)[1] - (a)[1]*(b)[0]; \
00112 }
00113 #define add3(a, b, c) { for (int i=0; i<3; ++i) (c)[i] = (a)[i] + (b)[i]; }
00114 #define sub3(a, b, c) { for (int i=0; i<3; ++i) (c)[i] = (a)[i] - (b)[i]; }
00115 #define trace(str) /* { vcl_cerr << str << vcl_endl; } */
00116 
00117 bool vgui_draw_line(double const T[4][4], double a, double b, double c)
00118 {
00119   double l[3] = { a, b, c };
00120 
00121   double M[3][3] = { // M = T([0 1 3], [0 1 3]);
00122     { T[0][0], T[0][1], T[0][3] },
00123     { T[1][0], T[1][1], T[1][3] },
00124     { T[3][0], T[3][1], T[3][3] }
00125   };
00126 
00127   double M0_l[3]; cross3(M[0], l, M0_l);
00128   double M1_l[3]; cross3(M[1], l, M1_l);
00129   double M2_l[3]; cross3(M[2], l, M2_l);
00130 
00131   double tmp[3];
00132   glBegin(GL_LINE_STRIP);
00133 
00134   // line x_dev = -w_dev :
00135   {
00136     add3(M0_l, M2_l, tmp);
00137     double y_dev = dot3(M[1], tmp);
00138     double w_dev = dot3(M[2], tmp);
00139     if (w_dev>0) {
00140       if (-w_dev<=y_dev && y_dev<=w_dev) {
00141         trace("x=-1"); glVertex4d( tmp[0],  tmp[1],  0,  tmp[2]); }
00142     }
00143     else if (w_dev<0) {
00144       if (-w_dev>=y_dev && y_dev>=w_dev) {
00145         trace("x=-1"); glVertex4d(-tmp[0], -tmp[1],  0, -tmp[2]); }
00146     }
00147   }
00148 
00149   // line x_dev = +w_dev :
00150   {
00151     sub3(M0_l, M2_l, tmp);
00152     double y_dev = dot3(M[1], tmp);
00153     double w_dev = dot3(M[2], tmp);
00154     if (w_dev>0) {
00155       if (-w_dev<=y_dev && y_dev<=w_dev) {
00156         trace("x=+1"); glVertex4d( tmp[0],  tmp[1],  0,  tmp[2]); }
00157     }
00158     else if (w_dev<0) {
00159       if (-w_dev>=y_dev && y_dev>=w_dev) {
00160         trace("x=+1"); glVertex4d(-tmp[0], -tmp[1],  0, -tmp[2]); }
00161     }
00162   }
00163 
00164   // line y_dev = -w_dev :
00165   {
00166     add3(M1_l, M2_l, tmp);
00167     double x_dev = dot3(M[0], tmp);
00168     double w_dev = dot3(M[2], tmp);
00169     if (w_dev>0) {
00170       if (-w_dev<=x_dev && x_dev<=w_dev) {
00171         trace("y=-1"); glVertex4d( tmp[0],  tmp[1],  0,  tmp[2]); }
00172     }
00173     else if (w_dev<0) {
00174       if (-w_dev>=x_dev && x_dev>=w_dev) {
00175         trace("y=-1"); glVertex4d(-tmp[0], -tmp[1],  0, -tmp[2]); }
00176     }
00177   }
00178 
00179   // line y_dev = +w_dev :
00180   {
00181     sub3(M1_l, M2_l, tmp);
00182     double x_dev = dot3(M[0], tmp);
00183     double w_dev = dot3(M[2], tmp);
00184     if (w_dev>0) {
00185       if (-w_dev<=x_dev && x_dev<=w_dev) {
00186         trace("y=+1"); glVertex4d( tmp[0],  tmp[1],  0,  tmp[2]); }
00187     }
00188     else if (w_dev<0) {
00189       if (-w_dev>=x_dev && x_dev>=w_dev) {
00190         trace("y=+1"); glVertex4d(-tmp[0], -tmp[1],  0, -tmp[2]); }
00191     }
00192   }
00193 
00194   trace("");
00195   glEnd();
00196 
00197   return true;
00198 }
00199 
00200 bool vgui_draw_line(double const P[4][4], double const M[4][4], double a, double b, double c)
00201 {
00202   double T[4][4];
00203   vgui_multiply_4x4(P, M, T);
00204   return vgui_draw_line(T, a, b, c);
00205 }
00206 
00207 bool vgui_draw_line(double a, double b, double c)
00208 {
00209   double P[4][4]; glGetDoublev(GL_PROJECTION_MATRIX, &P[0][0]); vgui_transpose_4x4(P);
00210   double M[4][4]; glGetDoublev(GL_MODELVIEW_MATRIX,  &M[0][0]); vgui_transpose_4x4(M);
00211   double T[4][4]; vgui_multiply_4x4(P, M, T);
00212   return vgui_draw_line(T, a, b, c);
00213 }