Re #589: refactored mirror (Boris)

The mirror is now rendered through an own viewport instead of to texture.

o replaced with code from cGrCarCamBehindReverse
o adapted new code to mirror viewport instead of fullscreen rendering
o renamed cGrCarCamMirror::setPos() to setScreenPos()
o put new functions before/afterDraw() to use to initialize mirror specialities
o cGrScreen::update(): removed unnecessary code
o cGrScreen::update(): moved mirror rendering after rendering of scene

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@4962 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: 00f6f93c0de7f74fdab77d37af2ea35b0cfc2e04
Former-commit-id: a0ff2de1efeb2cb061bb9bfc6dd0cd03805e399c
This commit is contained in:
kmetykog 2012-09-25 09:33:22 +00:00
parent 96f1fb2f69
commit 5360d04406
3 changed files with 89 additions and 113 deletions

View file

@ -486,33 +486,57 @@ class cGrCarCamInsideDynDriverEye : public cGrCarCamInsideDriverEye
// cGrCarCamMirror ================================================================
cGrCarCamMirror::~cGrCarCamMirror ()
cGrCarCamMirror::cGrCarCamMirror(cGrScreen *myscreen, int id, int drawCurr, int drawBG,
float myfovy, float myfovymin, float myfovymax,
float myfnear, float myffar,
float myfogstart, float myfogend)
: cGrPerspCamera(myscreen, id, drawCurr, 1, drawBG, 1,
myfovy, myfovymin, myfovymax,
myfnear, myffar, myfogstart, myfogend)
{
glDeleteTextures (1, &tex);
delete viewCam;
}
void cGrCarCamMirror::setModelView(void)
{
sgMat4 mat, mat2, mirror;
void cGrCarCamMirror::limitFov(void) {
fovy = 90.0 / screen->getViewRatio();
grMakeLookAtMat4(mat, eye, center, up);
#define M(row,col) mirror[row][col]
M(0,0) = 1.0; M(0,1) = 0.0; M(0,2) = 0.0; M(0,3) = 0.0;
M(1,0) = 0.0; M(1,1) =-1.0; M(1,2) = 0.0; M(1,3) = 0.0;
M(2,0) = 0.0; M(2,1) = 0.0; M(2,2) = 1.0; M(2,3) = 0.0;
M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
#undef M
sgMultMat4(mat2, mat, mirror);
grContext.setCamera(mat2);
}
void cGrCarCamMirror::update(tCarElt *car, tSituation * /* s */)
{
sgVec3 P, p;
P[0] = car->_bonnetPos_x;
P[0] = car->_bonnetPos_x - (car->_dimension_x/2); // behind car
P[1] = car->_bonnetPos_y;
P[2] = car->_bonnetPos_z;
sgXformPnt3(P, car->_posMat);
eye[0] = P[0];
eye[1] = P[1];
eye[2] = P[2];
p[0] = car->_bonnetPos_x - 30.0;
p[1] = car->_bonnetPos_y;
float offset = 0;
// Compute offset angle and bezel compensation)
if (spansplit && viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
}
p[0] = car->_bonnetPos_x + 30.0 * cos(offset);
p[1] = car->_bonnetPos_y + 30.0 * sin(offset);
p[2] = car->_bonnetPos_z;
sgXformPnt3(p, car->_posMat);
@ -523,6 +547,10 @@ void cGrCarCamMirror::update(tCarElt *car, tSituation * /* s */)
up[0] = car->_posMat[2][0];
up[1] = car->_posMat[2][1];
up[2] = car->_posMat[2][2];
speed[0] =car->pub.DynGCg.vel.x;
speed[1] =car->pub.DynGCg.vel.y;
speed[2] =car->pub.DynGCg.vel.z;
}
@ -532,91 +560,57 @@ void cGrCarCamMirror::setViewport(int x, int y, int w, int h)
vpy = y;
vpw = w;
vph = h;
if (viewCam) {
delete viewCam;
}
viewCam = new cGrOrthoCamera(screen, x, x + w, y, y + h);
limitFov();
vp_aspectratio = double(vph)/vpw;
}
void cGrCarCamMirror::setPos (int x, int y, int w, int h)
void cGrCarCamMirror::setScreenPos (int x, int y, int w, int h)
{
mx = x;
my = y;
mw = w;
mh = h;
// round up texture size to next power of two
tw = GfNearestPow2(w);
th = GfNearestPow2(h);
if (tw < w) {
tw *= 2;
}
if (th < h) {
th *= 2;
}
// Create texture object.
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glReadBuffer(GL_BACK);
glCopyTexImage2D(GL_TEXTURE_2D,
0, // map level,
GL_RGB, // internal format,
0, 0, tw, th,
0 ); // border
tsu = (float) mw / tw;
teu = 0.0;
tsv = 0.0;
tev = (float) mh / th;
m_centery = my + mh/2;
}
void cGrCarCamMirror::activateViewport (void)
void cGrCarCamMirror::beforeDraw (void)
{
glFrontFace( GL_CW );
/* The aspect ratio of the mirror is probably not the same
* as the real aspect ratio. Thus we do the following:
* 1) set up the mirror viewport with the same aspect ratio
* as the real scene
* 2) scissor the area of the actual mirror
*
* The viewport in 1) will be the same as the actual mirror,
* but with the height adjusted to fit the real aspect ratio.
* For that the mirror's height is calculated by multiplying
* the mirror's width with the real aspect ratio.
* To get the lower-left corner of the mirror's viewport half
* of that new height is subtracted from the mirror center's
* y-coordinate.
*/
double mvph = mw * vp_aspectratio;
int mvpy = m_centery - (mvph/2);
glViewport(mx, mvpy, mw, mvph);
glEnable(GL_SCISSOR_TEST);
glScissor(mx, my, mw, mh);
}
void cGrCarCamMirror::afterDraw (void)
{
glDisable(GL_SCISSOR_TEST);
glViewport(vpx, vpy, vpw, vph);
// Enable scissor test to conserve graphics memory bandwidth.
glEnable(GL_SCISSOR_TEST);
glScissor(vpx + (vpw - mw)/2, vpy + (vph - mh)/2, mw, mh);
glFrontFace( GL_CCW );
}
void cGrCarCamMirror::store (void)
{
glDisable(GL_SCISSOR_TEST);
glBindTexture(GL_TEXTURE_2D, tex);
glReadBuffer(GL_BACK);
// NVidia recommends to NOT use glCopyTexImage2D for performance reasons.
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
vpx + (vpw - mw)/2,
vpy + (vph - mh)/2, mw, mh);
}
void cGrCarCamMirror::display (void)
{
viewCam->action ();
glBindTexture (GL_TEXTURE_2D, tex);
glBegin(GL_TRIANGLE_STRIP);
{
glColor4f(1.0, 1.0, 1.0, 1.0);
glTexCoord2f(tsu, tsv); glVertex2f(mx, my);
glTexCoord2f(tsu, tev); glVertex2f(mx, my + mh);
glTexCoord2f(teu, tsv); glVertex2f(mx + mw, my);
glTexCoord2f(teu, tev); glVertex2f(mx + mw, my + mh);
}
glEnd();
}
// cGrCarCamInsideFixedCar ================================================================
class cGrCarCamInsideFixedCar : public cGrPerspCamera

View file

@ -247,34 +247,25 @@ class cGrCarCamMirror : public cGrPerspCamera
{
protected:
int vpx, vpy, vpw, vph; /* viewport size */
int tw, th; /* texture size */
double vp_aspectratio; /* viewport aspect ratio: vph/vpw */
int mx, my, mw, mh; /* drawing area */
float tsu, tsv, teu, tev; /* texture coord */
GLuint tex; /* texture */
cGrOrthoCamera *viewCam;
int m_centery; /* y-coordinate of the mirror's center point */
public:
cGrCarCamMirror(cGrScreen *myscreen, int id, int drawCurr, int drawBG,
float myfovy, float myfovymin, float myfovymax,
float myfnear, float myffar = 1500.0,
float myfogstart = 1400.0, float myfogend = 1500.0)
: cGrPerspCamera(myscreen, id, drawCurr, 1, drawBG, 1,
myfovy, myfovymin, myfovymax,
myfnear, myffar, myfogstart, myfogend) {
glGenTextures (1, &tex);
limitFov();
viewCam = NULL;
}
virtual ~cGrCarCamMirror ();
float myfogstart = 1400.0, float myfogend = 1500.0);
void update (tCarElt *car, tSituation *s);
void limitFov (void);
void setViewport (int x, int y, int w, int h);
void setPos (int x, int y, int w, int h);
void activateViewport (void);
void store (void);
void display (void);
void setScreenPos (int x, int y, int w, int h);
virtual void setModelView(void);
virtual void beforeDraw(void);
virtual void afterDraw(void);
};

View file

@ -133,7 +133,7 @@ void cGrScreen::activate(int x, int y, int w, int h, float v)
if (mirrorCam) {
// mirror width adjusted to fit board size
mirrorCam->setViewport (scrx, scry, scrw, scrh);
mirrorCam->setPos (scrx + scrw / 2 - (scrw * boardWidth /400),
mirrorCam->setScreenPos (scrx + scrw / 2 - (scrw * boardWidth /400),
scry + 5 * scrh / 6 - scrh / 10,
(scrw * boardWidth /200), scrh / 6);
}
@ -349,15 +349,6 @@ void cGrScreen::update(tSituation *s, const cGrFrameInfo* frameInfo)
curCam->onSelect(curCar, s);
}
/* Mirror */
if (mirrorFlag && curCam->isMirrorAllowed ()) {
mirrorCam->activateViewport ();
dispCam = mirrorCam;
glClear (GL_DEPTH_BUFFER_BIT);
camDraw (s);
mirrorCam->store ();
}
glEnable(GL_SCISSOR_TEST);
glViewport(scrx, scry, scrw, scrh);
glScissor(scrx, scry, scrw, scrh);
@ -374,11 +365,11 @@ void cGrScreen::update(tSituation *s, const cGrFrameInfo* frameInfo)
glDisable(GL_FOG);
glEnable(GL_TEXTURE_2D);
/* Mirror */
if (mirrorFlag && curCam->isMirrorAllowed ()) {
mirrorCam->display ();
glViewport (scrx, scry, scrw, scrh);
}
/* Mirror */
if (mirrorFlag && curCam->isMirrorAllowed ()) {
dispCam = mirrorCam;
camDraw (s);
}
GfProfStartProfile("boardCam*");
boardCam->action();