/*************************************************************************** file : grscreen.cpp created : Thu May 15 22:11:03 CEST 2003 copyright : (C) 2003 by Eric Espi� email : eric.espie@torcs.org version : $Id: grscreen.cpp,v 1.22 2006/09/05 23:05:52 berniw Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /** @file @author Eric Espie @version $Id: grscreen.cpp,v 1.22 2006/09/05 23:05:52 berniw Exp $ */ #include #include #include "grutil.h" #include "grmain.h" #include "grscene.h" #include "grshadow.h" #include "grskidmarks.h" #include "grcar.h" #include "grboard.h" #include "grcarlight.h" #include "grscreen.h" static char buf[1024]; static char path[1024]; static char path2[1024]; cGrScreen::cGrScreen(int myid) { id = myid; curCar = NULL; curCam = NULL; mirrorCam = NULL; dispCam = NULL; boardCam = NULL; bgCam = NULL; board = NULL; curCamHead = 0; drawCurrent = 0; active = 0; selectNextFlag = 0; selectPrevFlag = 0; mirrorFlag = 1; memset(cams, 0, sizeof(cams)); viewRatio = 1.33; cars = 0; } cGrScreen::~cGrScreen() { int i; class cGrCamera *cam; for (i = 0; i < 10; i++) { while ((cam = GF_TAILQ_FIRST(&cams[i])) != 0) { cam->remove(&cams[i]); delete cam; } } delete boardCam; delete mirrorCam; delete bgCam; if (board != NULL) { board->shutdown (); } FREEZ(cars); if (board != NULL) { delete board; board = NULL; } } int cGrScreen::isInScreen(int x, int y) { if (!active) { return 0; } if ((x >= scrx) && (y >= scry) && (x < (scrx + scrw)) && (y < (scry + scrh))) { return 1; } return 0; } void cGrScreen::setCurrentCar(tCarElt *newCurCar) { curCar = newCurCar; } /* Set Screen size & position */ void cGrScreen::activate(int x, int y, int w, int h) { viewRatio = (float)w / (float)h; scrx = x; scry = y; scrw = w; scrh = h; if (mirrorCam) { mirrorCam->setViewport (scrx, scry, scrw, scrh); mirrorCam->setPos (scrx + scrw / 4, scry + 5 * scrh / 6 - scrh / 10, scrw / 2, scrh / 6); } if (curCam) { curCam->limitFov (); curCam->setZoom (GR_ZOOM_DFLT); } active = 1; } void cGrScreen::desactivate(void) { active = 0; } /* Set camera zoom value */ void cGrScreen::setZoom(long zoom) { curCam->setZoom(zoom); } void cGrScreen::selectNextCar(void) { selectNextFlag = 1; } void cGrScreen::selectPrevCar(void) { selectPrevFlag = 1; } void cGrScreen::selectBoard(long brd) { board->selectBoard(brd); } void cGrScreen::selectTrackMap() { int viewmode; board->getTrackMap()->selectTrackMap(); viewmode = board->getTrackMap()->getViewMode(); sprintf(path, "%s/%d", GR_SCT_DISPMODE, id); GfParmSetNum(grHandle, path, GR_ATT_MAP, NULL, (tdble)viewmode); /* save also as user's preference if human */ if (curCar->_driverType == RM_DRV_HUMAN) { sprintf(path2, "%s/%s", GR_SCT_DISPMODE, curCar->_name); GfParmSetNum(grHandle, path2, GR_ATT_MAP, NULL, (tdble)viewmode); } GfParmWriteFile(NULL, grHandle, "Graph"); } void cGrScreen::switchMirror(void) { mirrorFlag = 1 - mirrorFlag; sprintf(path, "%s/%d", GR_SCT_DISPMODE, id); GfParmSetNum(grHandle, path, GR_ATT_MIRROR, NULL, (tdble)mirrorFlag); /* save also as user's preference if human */ if (curCar->_driverType == RM_DRV_HUMAN) { sprintf(path2, "%s/%s", GR_SCT_DISPMODE, curCar->_name); GfParmSetNum(grHandle, path2, GR_ATT_MIRROR, NULL, (tdble)mirrorFlag); } GfParmWriteFile(NULL, grHandle, "Graph"); } /* Select the camera by number */ void cGrScreen::selectCamera(long cam) { if (cam == curCamHead) { /* Same camera list, choose the next one */ curCam = curCam->next(); if (curCam == (cGrPerspCamera*)GF_TAILQ_END(&cams[cam])) { curCam = (cGrPerspCamera*)GF_TAILQ_FIRST(&cams[cam]); } } else { /* Change of camera list, take the first one */ curCamHead = cam; curCam = (cGrPerspCamera*)GF_TAILQ_FIRST(&cams[cam]); } if (curCam == NULL) { /* back to default camera */ curCamHead = 0; curCam = (cGrPerspCamera*)GF_TAILQ_FIRST(&cams[curCamHead]); } sprintf(path, "%s/%d", GR_SCT_DISPMODE, id); GfParmSetStr(grHandle, path, GR_ATT_CUR_DRV, curCar->_name); GfParmSetNum(grHandle, path, GR_ATT_CAM, (char*)NULL, (tdble)curCam->getId()); GfParmSetNum(grHandle, path, GR_ATT_CAM_HEAD, (char*)NULL, (tdble)curCamHead); /* save also as user's preference if human */ if (curCar->_driverType == RM_DRV_HUMAN) { sprintf(path2, "%s/%s", GR_SCT_DISPMODE, curCar->_name); GfParmSetNum(grHandle, path2, GR_ATT_CAM, (char*)NULL, (tdble)curCam->getId()); GfParmSetNum(grHandle, path2, GR_ATT_CAM_HEAD, (char*)NULL, (tdble)curCamHead); } sprintf(buf, "%s-%d-%d", GR_ATT_FOVY, curCamHead, curCam->getId()); curCam->loadDefaults(buf); drawCurrent = curCam->getDrawCurrent(); curCam->limitFov (); GfParmWriteFile(NULL, grHandle, "Graph"); } static class cGrPerspCamera *ThedispCam; /* the display camera */ static int comparCars(const void *car1, const void *car2) { float d1 = ThedispCam->getDist2(*(tCarElt**)car1); float d2 = ThedispCam->getDist2(*(tCarElt**)car2); if (d1 > d2) { return -1; } else { return 1; } } void cGrScreen::camDraw(tSituation *s) { int i; glDisable(GL_COLOR_MATERIAL); START_PROFILE("dispCam->update*"); dispCam->update(curCar, s); STOP_PROFILE("dispCam->update*"); if (dispCam->getDrawBackground()) { glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); grDrawBackground(dispCam, bgCam); glClear(GL_DEPTH_BUFFER_BIT); } glEnable(GL_DEPTH_TEST); START_PROFILE("dispCam->action*"); dispCam->action(); STOP_PROFILE("dispCam->action*"); START_PROFILE("grDrawCar*"); glFogf(GL_FOG_START, dispCam->getFogStart()); glFogf(GL_FOG_END, dispCam->getFogEnd()); glEnable(GL_FOG); /*sort the cars by distance for transparent windows */ ThedispCam = dispCam; qsort(cars, s->_ncars, sizeof(tCarElt*), comparCars); for (i = 0; i < s->_ncars; i++) { grDrawCar(cars[i], curCar, dispCam->getDrawCurrent(), dispCam->getDrawDriver(), s->currentTime, dispCam); } STOP_PROFILE("grDrawCar*"); START_PROFILE("grDrawScene*"); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); grDrawScene(); STOP_PROFILE("grDrawScene*"); } /* Update screen display */ void cGrScreen::update(tSituation *s, float Fps) { int i; ssgLight *light; int carChanged; if (!active) { return; } carChanged = 0; if (selectNextFlag) { for (i = 0; i < (s->_ncars - 1); i++) { if (curCar == s->cars[i]) { curCar = s->cars[i + 1]; curCar->priv.collision = 0; carChanged = 1; break; } } selectNextFlag = 0; } if (selectPrevFlag) { for (i = 1; i < s->_ncars; i++) { if (curCar == s->cars[i]) { curCar = s->cars[i - 1]; curCar->priv.collision = 0; carChanged = 1; break; } } selectPrevFlag = 0; } if (carChanged) { sprintf(path, "%s/%d", GR_SCT_DISPMODE, id); GfParmSetStr(grHandle, path, GR_ATT_CUR_DRV, curCar->_name); loadParams (s); GfParmWriteFile(NULL, grHandle, "Graph"); curCam->onSelect(curCar, s); } light = ssgGetLight (0); /* MIRROR */ if (mirrorFlag && curCam->isMirrorAllowed ()) { mirrorCam->activateViewport (); dispCam = mirrorCam; glClear (GL_DEPTH_BUFFER_BIT); camDraw (s); mirrorCam->store (); } glViewport(scrx, scry, scrw, scrh); dispCam = curCam; camDraw(s); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_ALPHA_TEST); glDisable(GL_FOG); glEnable(GL_TEXTURE_2D); /* MIRROR */ if (mirrorFlag && curCam->isMirrorAllowed ()) { mirrorCam->display (); glViewport (scrx, scry, scrw, scrh); } START_PROFILE("boardCam*"); boardCam->action(); STOP_PROFILE("boardCam*"); START_PROFILE("grDisp**"); glDisable(GL_TEXTURE_2D); TRACE_GL("cGrScreen::update glDisable(GL_DEPTH_TEST)"); board->refreshBoard(s, Fps, 0, curCar); TRACE_GL("cGrScreen::update display boards"); STOP_PROFILE("grDisp**"); } void cGrScreen::loadParams(tSituation *s) { int camNum; int i; class cGrCamera *cam; char *carName; sprintf(path, "%s/%d", GR_SCT_DISPMODE, id); if (!curCar) { carName = GfParmGetStr(grHandle, path, GR_ATT_CUR_DRV, ""); for (i = 0; i < s->_ncars; i++) { if (!strcmp(s->cars[i]->_name, carName)) { break; } } if (i < s->_ncars) { curCar = s->cars[i]; } else if (id < s->_ncars) { curCar = s->cars[id]; } else { curCar = s->cars[0]; } } sprintf(path2, "%s/%s", GR_SCT_DISPMODE, curCar->_name); curCamHead = (int)GfParmGetNum(grHandle, path, GR_ATT_CAM_HEAD, NULL, 9); camNum = (int)GfParmGetNum(grHandle, path, GR_ATT_CAM, NULL, 0); mirrorFlag = (int)GfParmGetNum(grHandle, path, GR_ATT_MIRROR, NULL, (tdble)mirrorFlag); curCamHead = (int)GfParmGetNum(grHandle, path2, GR_ATT_CAM_HEAD, NULL, (tdble)curCamHead); camNum = (int)GfParmGetNum(grHandle, path2, GR_ATT_CAM, NULL, (tdble)camNum); mirrorFlag = (int)GfParmGetNum(grHandle, path2, GR_ATT_MIRROR, NULL, (tdble)mirrorFlag); cam = GF_TAILQ_FIRST(&cams[curCamHead]); curCam = NULL; while (cam) { if (cam->getId() == camNum) { curCam = (cGrPerspCamera*)cam; break; } cam = cam->next(); } if (curCam == NULL) { // back to default camera curCamHead = 0; curCam = (cGrPerspCamera*)GF_TAILQ_FIRST(&cams[curCamHead]); GfParmSetNum(grHandle, path, GR_ATT_CAM, NULL, (tdble)curCam->getId()); GfParmSetNum(grHandle, path, GR_ATT_CAM_HEAD, NULL, (tdble)curCamHead); } sprintf(buf, "%s-%d-%d", GR_ATT_FOVY, curCamHead, curCam->getId()); curCam->loadDefaults(buf); drawCurrent = curCam->getDrawCurrent(); board->loadDefaults(curCar); } /* Create cameras */ void cGrScreen::initCams(tSituation *s) { tdble fovFactor; int i; fovFactor = GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_FOVFACT, (char*)NULL, 1.0); fovFactor *= GfParmGetNum(grTrackHandle, TRK_SECT_GRAPH, TRK_ATT_FOVFACT, (char*)NULL, 1.0); if (boardCam == NULL) { boardCam = new cGrOrthoCamera(this,0, grWinw*600/grWinh, 0, 600); } if (bgCam == NULL) { bgCam = new cGrBackgroundCam(this); } if (mirrorCam == NULL) { mirrorCam = new cGrCarCamMirror( this, -1, 0, // drawCurr 1, // drawBG 90.0, // fovy 0.0, // fovymin 360.0, // fovymax 0.3, // near 300.0 * fovFactor, // far 200.0 * fovFactor, // fog1 300.0 * fovFactor // fog ); } // Scene Cameras memset(cams, 0, sizeof(cams)); grCamCreateSceneCameraList(this, cams, fovFactor); cars = (tCarElt**)calloc(s->_ncars, sizeof (tCarElt*)); for (i = 0; i < s->_ncars; i++) { cars[i] = s->cars[i]; } loadParams(s); } void cGrScreen::initBoard(void) { if (board == NULL) { board = new cGrBoard (id); } board->initBoard (); }