Patch from Andy Ross:
Actually, I think I'm off the hook here; the problem is pre-existing. What's happening is that the x/y offsets enter the modelview matrix at line 346 in the current panel.cxx. But note that the same transformation also occurs before each instrument rendered at line 403. What's happening is that the instruments are double-translated relative to the background. Unless I'm not understanding something, the one inside the instrument render loop looks unnecessary. Removing it fixes the issue and doesn't cause any bugs that I can find. It also fixes a bug where you could scroll the instruments on top of the 3D panel, where the offsets are supposed to be ignored. :) Attached is a new panel.cxx which fixes that bug, and substantially simplifies the virtual panel code (the matrix inversion that I thought was needed wasn't, but there were some offsetting scale bugs that hid the problem).
This commit is contained in:
parent
b9d1cad6f2
commit
f477a4603b
1 changed files with 24 additions and 64 deletions
|
@ -400,7 +400,6 @@ FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
|
|||
for ( ; current != end; current++) {
|
||||
FGPanelInstrument * instr = *current;
|
||||
glPushMatrix();
|
||||
glTranslated(x_offset, y_offset, 0);
|
||||
glTranslated(instr->getXPos(), instr->getYPos(), 0);
|
||||
instr->draw();
|
||||
glPopMatrix();
|
||||
|
@ -419,52 +418,25 @@ FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
|
|||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
|
||||
// Yanked from the YASim codebase. Should probably be replaced with
|
||||
// the 4x4 routine from plib, which is more appropriate here.
|
||||
static void invert33Matrix(float* m)
|
||||
{
|
||||
// Compute the inverse as the adjoint matrix times 1/(det M).
|
||||
// A, B ... I are the cofactors of a b c
|
||||
// d e f
|
||||
// g h i
|
||||
float a=m[0], b=m[1], c=m[2];
|
||||
float d=m[3], e=m[4], f=m[5];
|
||||
float g=m[6], h=m[7], i=m[8];
|
||||
|
||||
float A = (e*i - h*f);
|
||||
float B = -(d*i - g*f);
|
||||
float C = (d*h - g*e);
|
||||
float D = -(b*i - h*c);
|
||||
float E = (a*i - g*c);
|
||||
float F = -(a*h - g*b);
|
||||
float G = (b*f - e*c);
|
||||
float H = -(a*f - d*c);
|
||||
float I = (a*e - d*b);
|
||||
|
||||
float id = 1/(a*A + b*B + c*C);
|
||||
|
||||
m[0] = id*A; m[1] = id*D; m[2] = id*G;
|
||||
m[3] = id*B; m[4] = id*E; m[5] = id*H;
|
||||
m[6] = id*C; m[7] = id*F; m[8] = id*I;
|
||||
}
|
||||
|
||||
void
|
||||
FGPanel::setupVirtualCockpit()
|
||||
{
|
||||
int i;
|
||||
FGViewer* view = globals->get_current_view();
|
||||
|
||||
// Corners for the panel quad. These numbers put a "standard"
|
||||
// panel at 1m from the eye, with a horizontal size of 60 degrees,
|
||||
// and with its center 5 degrees down. This will work well for
|
||||
// most typical screen-space panel definitions. In principle,
|
||||
// these should be settable per-panel, so that you can have lots
|
||||
// of panel objects plastered about the cockpit in realistic
|
||||
// Generate corners for the panel quad. Put the top edge of the
|
||||
// panel 1m in and 6 degrees down from the forward direction, and
|
||||
// make the whole thing 60 degrees wide. In principle, these
|
||||
// should be settable per-panel, so that you can have lots of
|
||||
// panel objects plastered about the cockpit in realistic
|
||||
// positions and orientations.
|
||||
float DY = .0875; // tan(5 degrees)
|
||||
float a[] = { -0.5773503, -0.4330172 - DY, -1 }; // bottom left
|
||||
float b[] = { 0.5773503, -0.4330172 - DY, -1 }; // bottom right
|
||||
float c[] = { -0.5773503, 0.4330172 - DY, -1 }; // top left
|
||||
float a[3], b[3], c[3];
|
||||
float pw = tan(30*SGD_DEGREES_TO_RADIANS);
|
||||
float ph = 2 * pw * (float)_height/(float)_width;
|
||||
float ptop = -tan(6*SGD_DEGREES_TO_RADIANS);
|
||||
a[0] = -pw; a[1] = ptop-ph; a[2] = -1; // bottom left
|
||||
b[0] = pw; b[1] = ptop-ph; b[2] = -1; // bottom right
|
||||
c[0] = -pw; c[1] = ptop; c[2] = -1; // top left
|
||||
|
||||
// A standard projection, in meters, with especially close clip
|
||||
// planes.
|
||||
|
@ -476,6 +448,7 @@ FGPanel::setupVirtualCockpit()
|
|||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
// Generate a "look at" matrix using OpenGL (!) coordinate
|
||||
// conventions.
|
||||
|
@ -492,42 +465,29 @@ FGPanel::setupVirtualCockpit()
|
|||
glTranslatef(a[0], a[1], a[2]);
|
||||
|
||||
// Generate a matrix to translate unit square coordinates from the
|
||||
// panel to real world coordinates. Use a basis for the panel
|
||||
// quad and invert. Note: this matrix is relatively expensive to
|
||||
// panel to real world coordinates. Use a transposed basis for
|
||||
// the panel quad. Note: this matrix is relatively expensive to
|
||||
// compute, and is invariant. Consider precomputing and storing
|
||||
// it. Also, consider using the plib vector math routines, so the
|
||||
// reuse junkies don't yell at me. (Fine, I hard-coded a cross
|
||||
// product. Just shoot me and be done with it.)
|
||||
float u[3], v[3], w[3], m[9];
|
||||
float u[3], v[3], w[3], m[16];
|
||||
for(i=0; i<3; i++) u[i] = b[i] - a[i]; // U = B - A
|
||||
for(i=0; i<3; i++) v[i] = c[i] - a[i]; // V = C - A
|
||||
w[0] = u[1]*v[2] - v[1]*u[2]; // W = U x V
|
||||
w[1] = u[2]*v[0] - v[2]*u[0];
|
||||
w[2] = u[0]*v[1] - v[0]*u[1];
|
||||
for(int i=0; i<3; i++) { // |Ux Uy Uz|-1
|
||||
m[i] = u[i]; // m =|Vx Vy Vz|
|
||||
m[i+3] = v[i]; // |Wx Wy Wz|
|
||||
m[i+6] = w[i];
|
||||
}
|
||||
invert33Matrix(m);
|
||||
|
||||
float glm[16]; // Expand to a 4x4 OpenGL matrix.
|
||||
glm[0] = m[0]; glm[4] = m[1]; glm[8] = m[2]; glm[12] = 0;
|
||||
glm[1] = m[3]; glm[5] = m[4]; glm[9] = m[5]; glm[13] = 0;
|
||||
glm[2] = m[6]; glm[6] = m[7]; glm[10] = m[8]; glm[14] = 0;
|
||||
glm[3] = 0; glm[7] = 0; glm[11] = 0; glm[15] = 1;
|
||||
glMultMatrixf(glm);
|
||||
m[0] = u[0]; m[4] = v[0]; m[8] = w[0]; m[12] = 0; // |Ux Vx Wx|
|
||||
m[1] = u[1]; m[5] = v[1]; m[9] = w[1]; m[13] = 0; // m = |Uy Vy Wy|
|
||||
m[2] = u[2]; m[6] = v[2]; m[10] = w[2]; m[14] = 0; // |Uz Vz Wz|
|
||||
m[3] = 0; m[7] = 0; m[11] = 0; m[15] = 1;
|
||||
glMultMatrixf(m);
|
||||
|
||||
// Finally, a scaling factor to convert the 1024x768 range the
|
||||
// panel uses to a unit square mapped to the panel quad.
|
||||
glScalef(1./1024, 1./768, 1);
|
||||
// Finally, a scaling factor to map the panel's width and height
|
||||
// to the unit square.
|
||||
glScalef(1./_width, 1./_height, 1);
|
||||
|
||||
// Scale to the appropriate vertical size. I'm not quite clear on
|
||||
// this yet; an identical scaling is not appropriate for
|
||||
// _width, for example. This should probably go away when panel
|
||||
// coordinates get sanified for virtual cockpits.
|
||||
glScalef(1, _height/768.0, 1);
|
||||
|
||||
// Now, turn off the Z buffer. The panel code doesn't need
|
||||
// it, and we're using different clip planes anyway (meaning we
|
||||
// can't share it without glDepthRange() hackery or much
|
||||
|
|
Loading…
Reference in a new issue