forked from speed-dreams/speed-dreams-code
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:
parent
01ca9970b5
commit
29a9968df0
4 changed files with 183 additions and 49 deletions
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue