Ой, так что у вас есть реализация SW без камеры HW ...
Я имел в виду реальный эффект перекоса на английском языке, называемый Рулонный затвор : если вы получаете изображение, перемещая реальную камеру сканирования HW (без TDI технология ) затем появляется эффект перекоса + размытия, скользящий по линиям сканирования ... попробуйте сделать фотографию из бокового окна движущегося автомобиля, изображение будет искажено.
Эффект , который вы описываете , не имеет ничего общего с перекосом, это просто математическая «особенность», извините, у меня нет имени для него.
Поскольку ваша камера SW , только вы можете влиять на панорамирование и масштабирование по своему вкусу, поэтому я просто вычислю zoom
с камеры FOV и pan
. Я вижу это так:
![overview](https://i.stack.imgur.com/t8gTH.png)
Итак:
I. a = FOV / zoom
II. tan(0.5*a) = (x1-x0) / h
------------------------
zoom = 0.5*FOV/atan( (x1-x0) / h )
Где h
- высота потолка, x0
- положение камеры (панорамирования), x0
- положение края бумаги, а FOV
- поле обзора вашей камеры без увеличения ...
[edit1] вставка бумаги и анимация ...
Я закончил с этим:
![animation](https://i.stack.imgur.com/QgB4U.gif)
Здесь код C ++ / VCL для этого:
//---------------------------------------------------------------------------
double x0,x1,w=50,h=200,FOVx=60.0*M_PI/180.0,zoom,pan;
double t=0; // animation parameter <0,1>
//---------------------------------------------------------------------------
void TMain::draw()
{
if (!_redraw) return;
// clear buffer
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
double y0,y1,dx;
// position side view onto screen based on its size xs,ys
y0=0.5*(ys-h);
y1=y0+h;
x0=0.5*xs;
x1=x0+(h*tan(0.5*FOVx));
// compute zoom,pan from t
pan=(x1-x0+(0.5*w))*t;
zoom=0.5*FOVx/atan(((1.0-t)*(x1-x0)+(0.5*w*t))/h);
// scene
bmp->Canvas->Pen->Color=clBlue;
bmp->Canvas->MoveTo( 0,y0);
bmp->Canvas->LineTo(xs,y0);
bmp->Canvas->MoveTo( 0,y1);
bmp->Canvas->LineTo(xs,y1);
// paper
bmp->Canvas->Pen->Color=clRed;
bmp->Canvas->MoveTo(x1,y1);
bmp->Canvas->LineTo(x1+w,y1);
// FOVx
dx=h*tan(0.5*FOVx/zoom);
bmp->Canvas->Pen->Color=clAqua;
bmp->Canvas->MoveTo(x0+pan-dx,y1);
bmp->Canvas->LineTo(x0+pan,y0);
bmp->Canvas->LineTo(x0+pan+dx,y1);
// points
dx=4;
bmp->Canvas->Pen->Color=clAqua;
bmp->Canvas->Brush->Color=clBlue;
bmp->Canvas->Ellipse(x0-dx,y0-dx,x0+dx,y0+dx);
bmp->Canvas->Ellipse(x0+pan-dx,y0-dx,x0+pan+dx,y0+dx);
bmp->Canvas->Ellipse(x1-dx,y1-dx,x1+dx,y1+dx);
bmp->Canvas->Font->Color=clYellow;
bmp->Canvas->Brush->Style=bsClear;
bmp->Canvas->TextOutA(x0,y0-20,"x0");
bmp->Canvas->TextOutA(x0+pan+20,y0+5,"x0+pan");
bmp->Canvas->TextOutA(x1,y1+5,"x1");
bmp->Canvas->Brush->Style=bsSolid;
// render backbuffer
Main->Canvas->Draw(0,0,bmp);
_redraw=false;
}
//---------------------------------------------------------------------------
Если вы игнорируете рендеринг, вот что для вас важно:
pan=(x1-x0+(0.5*w))*t;
zoom=0.5*FOVx/atan(((1.0-t)*(x1-x0)+(0.5*w*t))/h);
Таким образом, я немного изменил значение x1
(это другой край бумаги) и вместо x1
в исходных уравнениях, приведенных выше, я использовал x1+w*t
, что означает, что бумага не видна в начале (t=0
), но это касается его снаружи, и оно полностью видно, когда (t=1)
. Остальное только результат замещения ...
w
- это ширина бумаги, t=<0.0,1.0>
- это параметр анимации, а все остальные значения не меняли значения ...
Анимация просто увеличивает t
на 0.02
в таймере 150 мс, записанном моим GIF-кодером (вот почему он такой прерывистый)