Bug #532 first implementation of MonitorArc compensation

Intended to allow the curvature of the monitors to be localed behind driver
(ie. distance between driver and center of each monitor is not the same),
this will cause some distortion unless bezel, distance and arc are entered
accurately.

Disabled by default, enable in the 'Advanced Graphic' configuration menu.

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

Former-commit-id: 245e6ef4e9db18133e2607d2b2fb5d3c99978100
Former-commit-id: a48ebdbb8a8627d78e2b8006d22d27bc79812c0a
This commit is contained in:
mungewell 2013-02-11 19:07:55 +00:00
parent 01ca9970b5
commit 29a9968df0
4 changed files with 183 additions and 49 deletions

View file

@ -105,11 +105,13 @@
#define GR_ATT_MONITOR "monitor type"
#define GR_VAL_MONITOR_16BY9 "16:9"
#define GR_VAL_MONITOR_4BY3 "4:3"
#define GR_VAL_MONITOR_NONE "None"
#define GR_ATT_SPANSPLIT "span splits"
#define GR_VAL_MONITOR_NONE "none"
#define GR_ATT_SPANSPLIT "span splits"
#define GR_VAL_YES "yes"
#define GR_VAL_NO "no"
#define GR_ATT_BEZELCOMP "bezel compensation"
#define GR_ATT_BEZELCOMP "bezel compensation"
#define GR_ATT_SCREENDIST "screen distance"
#define GR_ATT_ARCRATIO "arc ratio"
// Dash colours
#define GFSCR_SECT_DASHSETTINGS "Dash settings"

View file

@ -30,7 +30,9 @@
static char path[1024];
static float spanfovy;
static float bezelcomp;
static float bezelComp;
static float screenDist;
static float arcRatio;
static float spanaspect;
static tdble spanA;
@ -108,6 +110,7 @@ cGrPerspCamera::cGrPerspCamera(class cGrScreen *myscreen, int id, int drawCurr,
fogend = myfogend;
viewOffset = 0;
spanOffset = 0;
}
void cGrPerspCamera::setProjection(void)
@ -123,6 +126,14 @@ void cGrPerspCamera::setProjection(void)
float fovx = atan(getAspectRatio() / spanaspect * tan(fovy * M_PI / 360.0)) * 360.0 / M_PI;
grContext.setFOV(fovx, fovy);
grContext.setNearFar(fnear, ffar);
// correct view for split screen spanning
if (viewOffset) {
sgFrustum * frus = grContext.getFrustum();
frus->setFrustum(frus->getLeft() + spanOffset, frus->getRight() + spanOffset,
frus->getBot(), frus->getTop(), frus->getNear(), frus->getFar());
}
}
void cGrPerspCamera::setModelView(void)
@ -167,12 +178,68 @@ float cGrPerspCamera::getLODFactor(float x, float y, float z) {
return res;
}
float cGrPerspCamera::getSpanAngle(void)
{
float angle = 0;
// check if already computed
if (fovy == spanfovy)
return spanAngle;
fovy = spanfovy;
//PreCalculate the spanOffset
if (viewOffset) {
//=2*$A$2*tan($D$2*$C$2/2)
float width = (bezelComp / 100) * screenDist * tan(screen->getViewRatio() / spanaspect * (spanfovy * M_PI / 360.0 * 2)) / 2;
#if 1
// New method
float fovxR;
if (arcRatio > 0) {
//=if($B$2=0,0,atan($A$5/(2*($A$2/$B$2)))*2)
fovxR = 2 * atan(width / (2 * screenDist / arcRatio));
//=A10*$B$5
angle = (viewOffset - 10) * fovxR * 2;
//=if($B$2=0, A10*$A$5, abs(tan(B10)*($A$2-($A$2/$B$2)))/sqrt(tan(B10)^2+1))*if(A1>0,-1,1)
spanOffset = fabs(tan(angle) * (screenDist - (screenDist / arcRatio))) / sqrt((tan(angle) * tan(angle)) + 1); // / 2;
if (viewOffset < 10) spanOffset *= -1;
} else {
// monitors mounted flat on wall
spanOffset = (viewOffset - 10) * width / 2 ;
}
#else
// Old method
angle = (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelComp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
spanOffset = 0;
#endif
spanAngle = angle;
GfLogInfo("ViewOffset %f : fovy %f, arcRatio %f => width %f, angle %f, SpanOffset %f\n", viewOffset, fovy, arcRatio, width, angle, spanOffset);
}
return angle;
}
void cGrPerspCamera::setViewOffset(float newOffset)
{
if (newOffset)
spanfovy = fovy;
viewOffset = newOffset;
//PreCalculate the spanAngle and spanOffset
if (newOffset) {
spanfovy = fovy;
fovy = 0;
spanAngle = getSpanAngle();
} else {
//spanAngle = 0;
spanOffset = 0;
}
}
void cGrPerspCamera::setZoom(int cmd)
@ -213,8 +280,14 @@ void cGrPerspCamera::setZoom(int cmd)
limitFov();
if (viewOffset)
if (viewOffset) {
spanfovy = fovy;
fovy = 0;
spanAngle = getSpanAngle();
} else {
//spanAngle = 0;
spanOffset = 0;
}
sprintf(buf, "%s-%d-%d", GR_ATT_FOVY, screen->getCurCamHead(), getId());
sprintf(path, "%s/%d", GR_SCT_DISPMODE, screen->getId());
@ -313,9 +386,7 @@ class cGrCarCamInsideDriverEye : public cGrPerspCamera
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = car->_drvPos_x + 30.0 * cos(2*PI/3 * car->_glance + offset);
@ -385,9 +456,7 @@ class cGrCarCamInsideDynDriverEye : public cGrCarCamInsideDriverEye
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = car->_drvPos_x + 30.0 * cos(2*PI/3 * car->_glance + offset);
@ -616,9 +685,7 @@ class cGrCarCamInsideFixedCar : public cGrPerspCamera
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = car->_bonnetPos_x + 30.0 * cos(2*PI/3 * car->_glance + offset);
@ -671,9 +738,7 @@ class cGrCarCamInfrontFixedCar : public cGrPerspCamera
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = (car->_dimension_x / 2) + 30.0 * cos(2*PI/3 * car->_glance + offset);
@ -728,9 +793,7 @@ class cGrCarCamBehindFixedCar : public cGrPerspCamera
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = car->_drvPos_x - 6.0f * cos(PI * car->_glance) + 30.0 * cos(PI * car->_glance + offset);
@ -800,9 +863,7 @@ class cGrCarCamBehindReverse : public cGrPerspCamera
// Compute offset angle and bezel compensation)
if (viewOffset) {
offset += (viewOffset - 10 + (int((viewOffset - 10) * 2) * (bezelcomp - 100)/200)) *
atan(screen->getViewRatio() / spanaspect * tan(spanfovy * M_PI / 360.0)) * 2;
fovy = spanfovy;
offset += getSpanAngle();
}
P[0] = car->_bonnetPos_x - (car->_dimension_x/2) + 30.0 * cos(offset);
@ -1773,7 +1834,9 @@ grCamCreateSceneCameraList(class cGrScreen *myscreen, tGrCamHead *cams,
class cGrCamera *cam;
/* Check Bezel compensation - used when spaning view across multiple splits */
bezelcomp = (float)GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", 110);
bezelComp = (float)GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", 110);
screenDist= (float)GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_SCREENDIST, NULL, 1);
arcRatio = (float)GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_ARCRATIO, NULL, 1.0);
const char *pszMonitorType =
GfParmGetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_MONITOR, GR_VAL_MONITOR_16BY9);

View file

@ -168,6 +168,8 @@ class cGrPerspCamera : public cGrCamera
float fogstart;
float fogend;
float viewOffset;
float spanAngle;
float spanOffset;
public:
cGrPerspCamera(class cGrScreen *myscreen, int id, int drawCurr, int drawDrv, int drawBG, int mirrorAllowed,
@ -178,6 +180,7 @@ class cGrPerspCamera : public cGrCamera
virtual void setProjection(void);
virtual void setModelView(void);
virtual void loadDefaults(char *attr);
float getSpanAngle(void);
void setViewOffset(float newOffset);
virtual void setZoom(int cmd);
float getLODFactor(float x, float y, float z);

View file

@ -63,8 +63,12 @@ static int ForestIndex = 0;
static int TreeIndex = 0;
static int ParkingIndex = 0;
static int SpansplitIndex = 0;
static float BezelValue = 110.0f;
static int BezelValueId;
static float BezelComp = 110.0f;
static int BezelCompId;
static float ScreenDist = 1.0f;
static int ScreenDistId;
static float ArcRatio = 1.0f;
static int ArcRatioId;
static int MonitorIndex = 0;
static char buf[512];
@ -138,16 +142,38 @@ loadOptions()
}
}
BezelValue = GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", 110.0f);
if (BezelValue>150.0f) {
BezelValue = 150.0f;
BezelComp = GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", 110.0f);
if (BezelComp > 150.0f) {
BezelComp = 150.0f;
}
else if (BezelValue < 50.0f) {
BezelValue = 50.0f;
else if (BezelComp < 50.0f) {
BezelComp = 50.0f;
}
sprintf(buf, "%g", BezelValue);
GfuiEditboxSetString(ScrHandle, BezelValueId, buf);
sprintf(buf, "%g", BezelComp);
GfuiEditboxSetString(ScrHandle, BezelCompId, buf);
ScreenDist = GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_SCREENDIST, NULL, 1.0f);
if (ScreenDist > 5.0f) {
ScreenDist = 5.0f;
}
else if (ScreenDist < 0.0f) {
ScreenDist = 0.0f;
}
sprintf(buf, "%g", ScreenDist);
GfuiEditboxSetString(ScrHandle, ScreenDistId, buf);
ArcRatio = GfParmGetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_ARCRATIO, NULL, 1.0f);
if (ArcRatio > 1.0f) {
ArcRatio = 1.0f;
}
else if (ArcRatio < 0.0f) {
ArcRatio = 0.0f;
}
sprintf(buf, "%g", ArcRatio);
GfuiEditboxSetString(ScrHandle, ArcRatioId, buf);
MonitorIndex = 0; // Default value index, in case file value not found in list.
const char* pszMonitor =
@ -178,7 +204,9 @@ saveOptions()
GfParmSetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_AGR_TREE, TreeValues[TreeIndex]);
GfParmSetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_AGR_PARKING, ParkingValues[ParkingIndex]);
GfParmSetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_SPANSPLIT, SpansplitValues[SpansplitIndex]);
GfParmSetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", BezelValue);
GfParmSetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_BEZELCOMP, "%", BezelComp);
GfParmSetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_SCREENDIST, NULL, ScreenDist);
GfParmSetNum(grHandle, GR_SCT_GRAPHIC, GR_ATT_ARCRATIO, NULL, ArcRatio);
GfParmSetStr(grHandle, GR_SCT_GRAPHIC, GR_ATT_MONITOR, MonitorValues[MonitorIndex]);
GfParmWriteFile(NULL, grHandle, "graph");
@ -227,22 +255,54 @@ onChangeSpansplit(void* vp)
SpansplitIndex = (SpansplitIndex + NbSpansplitValues + delta) % NbSpansplitValues;
GfuiLabelSetText(ScrHandle, SpansplitLabelId, SpansplitValues[SpansplitIndex]);
GfuiEnable(ScrHandle, BezelValueId, SpansplitIndex ? GFUI_ENABLE : GFUI_DISABLE);
GfuiEnable(ScrHandle, BezelCompId, SpansplitIndex ? GFUI_ENABLE : GFUI_DISABLE);
GfuiEnable(ScrHandle, ScreenDistId, SpansplitIndex ? GFUI_ENABLE : GFUI_DISABLE);
GfuiEnable(ScrHandle, ArcRatioId, SpansplitIndex ? GFUI_ENABLE : GFUI_DISABLE);
}
static void
onChangeBezel(void * )
onChangeBezelComp(void * )
{
char* val = GfuiEditboxGetString(ScrHandle, BezelValueId);
sscanf(val, "%g", &BezelValue);
if (BezelValue > 150.0f)
BezelValue = 150.0f;
else if (BezelValue < 50.0f)
BezelValue = 50.0f;
char* val = GfuiEditboxGetString(ScrHandle, BezelCompId);
sscanf(val, "%g", &BezelComp);
if (BezelComp > 150.0f)
BezelComp = 150.0f;
else if (BezelComp < 50.0f)
BezelComp = 50.0f;
char buf[32];
sprintf(buf, "%g", BezelValue);
GfuiEditboxSetString(ScrHandle, BezelValueId, buf);
sprintf(buf, "%g", BezelComp);
GfuiEditboxSetString(ScrHandle, BezelCompId, buf);
}
static void
onChangeScreenDist(void * )
{
char* val = GfuiEditboxGetString(ScrHandle, ScreenDistId);
sscanf(val, "%g", &ScreenDist);
if (ScreenDist > 25.0f)
ScreenDist = 25.0f;
else if (ScreenDist < 0.1f)
ScreenDist = 0.1f;
char buf[32];
sprintf(buf, "%g", ScreenDist);
GfuiEditboxSetString(ScrHandle, ScreenDistId, buf);
}
static void
onChangeArcRatio(void * )
{
char* val = GfuiEditboxGetString(ScrHandle, ArcRatioId);
sscanf(val, "%g", &ArcRatio);
if (ArcRatio > 1.0f)
ArcRatio = 1.0f;
else if (ArcRatio < 0.0f)
ArcRatio = 0.0f;
char buf[32];
sprintf(buf, "%g", ArcRatio);
GfuiEditboxSetString(ScrHandle, ArcRatioId, buf);
}
static void
@ -264,7 +324,9 @@ onActivate(void* /* dummy */)
onChangeTree(0);
onChangeParking(0);
onChangeSpansplit(0);
onChangeBezel(0);
onChangeBezelComp(0);
onChangeScreenDist(0);
onChangeArcRatio(0);
onChangeMonitor(0);
}
@ -328,7 +390,11 @@ AdvancedGraphMenuInit(void* prevMenu)
GfuiMenuCreateButtonControl(ScrHandle, param, "spansplitrightarrow", (void*)1, onChangeSpansplit);
SpansplitLabelId = GfuiMenuCreateLabelControl(ScrHandle, param, "spansplitlabel");
BezelValueId = GfuiMenuCreateEditControl(ScrHandle, param, "bezeledit", NULL, NULL, onChangeBezel);
BezelCompId = GfuiMenuCreateEditControl(ScrHandle, param, "bezelcompedit", NULL, NULL, onChangeBezelComp);
ScreenDistId = GfuiMenuCreateEditControl(ScrHandle, param, "screendistedit", NULL, NULL, onChangeScreenDist);
ArcRatioId = GfuiMenuCreateEditControl(ScrHandle, param, "arcratioedit", NULL, NULL, onChangeArcRatio);
MonitorLeftButtonId =
GfuiMenuCreateButtonControl(ScrHandle, param, "monitorleftarrow", (void*)-1, onChangeMonitor);