我正在为HTML5 Canvas编写,将其用作视口,在该视口上保持中心原点和缩放级别。我想跟踪和缩放到某个区域,但是遇到了自然发生的效果,破坏了我试图获得的外观。这个问题关系到我如何在保留自然外观效果的同时减轻这种情况。
想象一下,我在天花板上安装了一个指向下方的摄像头,在地板上的某处是一张纸。我以恒定的速度沿着天花板移动相机,直到它位于纸张上方,同时以线性速率进行缩放,以便纸张最终填充渲染的图像。这些动作同时发生。
执行此操作时,可以观察到一种效果,使纸张在回到中心之前滑出框架。最好从视觉上进行解释,并保持在两个维度:
这不是一个很好的外观。考虑用户要求关注某事。他们的概念化是该实体正在进入视野,然后奇怪的是,它似乎先移开才靠近。
我想要的效果是目标对象仅接近框架的中心,而不会后退。我想答案是使缩放率(或移动率)变形。 ,尽管我不希望这样做),它可能是所涉及的距离的函数,或者人为地调整缩放比例,以使页面保持在框架中。理想情况下,我希望按照前一种方法为解决方案提供帮助。
更新:
我认为一个答案可能是将操作的缩放部分分为两个阶段。让问题的参数通知一个导数函数,该函数可得出渲染输出上目标中心和视口中心之间的距离,并找出最大的时间。对两个轴都执行此操作,并在两个轴之间选择一个时间:这是缩放阶段的边界。在第一阶段,缩放以使纸张恰好位于图像边界内。在第二阶段,放大到纸张以得到与以前相同的结果。
从直觉上看,这似乎更好,但是我仍然有两个问题。我无疑可以在 t 处找到 d 的方程式,但是我的演算很弱,我可能最终会进行最大采样而不是产生一个反函数来找到它。是我真正想要的。我也不确定如何在两个最大值之间进行选择以找到边界时间(尽管可能对此问题没有“正确”的答案,这对我来说也就不那么麻烦了)。我们将非常感谢您对任何问题的帮助,或对更广泛挑战的任何其他见解。
答案 0 :(得分:0)
好吧,所以您实现了不涉及硬件摄像机的软件实现....
我指的是英语中的真实偏斜效果,称为Rolling shutter:如果您通过移动真实的硬件扫描线摄像机(没有TDI technology)来获取图像,则偏斜+滑动扫描线时出现模糊效果...尝试从行驶中的汽车的侧窗拍摄照片,图像会偏斜。
您所描述的效果与偏斜无关,只是数学上的“奇异性”,对不起,我对此没有任何名字的建议。
由于您的摄像头是 SW ,因此您只能影响平移和缩放,因此我只需要根据摄像头 FOV 和{{ 1}}位置。我这样看:
所以:
zoom
其中pan
是最高高度, I. a = FOV / zoom
II. tan(0.5*a) = (x1-x0) / h
------------------------
zoom = 0.5*FOV/atan( (x1-x0) / h )
是摄像机(平移)位置,h
是纸张边缘位置,x0
是未缩放的视野相机...
[edit1]滑动纸张并播放动画...
我最终得到了这个
这是 C ++ / VCL 代码:
x0
如果忽略渲染内容,这对您来说很重要:
FOV
因此,我略微更改了//---------------------------------------------------------------------------
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)
是动画参数,其他所有值均未改变,表示...
动画只是在我的GIF编码器记录的150毫秒计时器中将w
增加t=<0.0,1.0>
(这就是为什么它如此断断续续的原因)