diff --git a/src/interfaces/graphic.h b/src/interfaces/graphic.h index ff816ab6..fdecf016 100644 --- a/src/interfaces/graphic.h +++ b/src/interfaces/graphic.h @@ -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" diff --git a/src/modules/graphic/ssggraph/grcam.cpp b/src/modules/graphic/ssggraph/grcam.cpp index 25c962c5..c7c61657 100644 --- a/src/modules/graphic/ssggraph/grcam.cpp +++ b/src/modules/graphic/ssggraph/grcam.cpp @@ -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); diff --git a/src/modules/graphic/ssggraph/grcam.h b/src/modules/graphic/ssggraph/grcam.h index 5ad7eb2b..3add6c50 100644 --- a/src/modules/graphic/ssggraph/grcam.h +++ b/src/modules/graphic/ssggraph/grcam.h @@ -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); diff --git a/src/modules/userinterface/legacymenu/confscreens/advancedgraphconfig.cpp b/src/modules/userinterface/legacymenu/confscreens/advancedgraphconfig.cpp index f92973b3..9bdd726d 100644 --- a/src/modules/userinterface/legacymenu/confscreens/advancedgraphconfig.cpp +++ b/src/modules/userinterface/legacymenu/confscreens/advancedgraphconfig.cpp @@ -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);