按:像PowerPoint那样对图片进行显示,可以增强显示效果,使图片显示比较有趣。准备将PowerPoint中的典型动画显示都实现。本文将实现一个简单的开个门效果的动画显示。
效果示例和算法的推导
效果如图所示:动画开始后,画面像一扇门一样关闭和打开。
下面进行算法的推导。
开个门的实际情形就是门的一端位置不变,而其余部分,逐渐从横向和纵深两个方向变短,门的上下边延长线交于视点。根据透视的原理,可以得到下面的几何图示。
Vp 为灭点, ABCD为原始图像(关闭的门),A’B’CD 为转动的图像,我们只要计算出A’B’ 的长度以及A’D子平面ABCD上的正投影的长度,就可以利用我们上一节的简单透视函数计算出A’B’CD在ABCD上图像(即投影或者眼睛看到的效果)。我们假定VP到ABCD平面的距离是Vd,根据相似三角形以及角B’CB(两个面的夹角,并非是这个角,我们暂且用它表示!!),可以得到
A’B = AB*(Vd-ADsin(角B’CB))/Vd
DJ = ADCos(角B’CB)
有了这两个数据,我们就可以得到转动到某个角度的图像,适当循环计算得到一些列图像。
补充说明:平面VpDC和ABCD的夹角是图像转到90度时对应的透视图中的最大角度。
示例代码
根据上述公式得到函数如下:
// src: the source image
// bOpenDoor: close door or open door demo
// times: displaying times
// interval: interval between the two displaying of the image, ms
// dir: LTDU , the four directions
// ctrWnd: the CWnd* of the control in which the image will be displayed
void CImgShape::showPerspectiveImage(CImage &src, bool bOpenDoor, int times, float interval, CString dir, CWnd *ctrWnd)
{
int iTopL;
CImage dst;
CRect rect;
ctrWnd->GetClientRect(&rect);
CDC* pDc = ctrWnd->GetDC();
int H, W;
if (dir == "U" || dir == "D") {
W = src.GetWidth();
H= src.GetHeight();
}
else {
H = src.GetWidth();
W = src.GetHeight();
}
float maxRotateAngle;
int tanVal = 6;// i.e. Vd explained above
maxRotateAngle = atan(tanVal);// the maximum angle between the square mentioned above
float viewDistance = W/2 * tanVal;//tan(maxRotateAngle)
float step = maxRotateAngle/times;
for (int i = 0; i < times; i++) {
float rotateAngle = step*i;
if (!bOpenDoor) {
rotateAngle = step * (times - i - 1);
}
int th = cos(rotateAngle)*H;
int tw= sin(rotateAngle)*H;
iTopL = (viewDistance - tw)/ viewDistance*W;
perspectiveImage(src, th, iTopL, dir, dst);//refer to the previous chapter please
dst.Draw(pDc->m_hDC,
rect.left,
0,
rect.Width(),
rect.Height());
Sleep(interval);
}
ctrWnd->ReleaseDC(pDc);
}
说明:上述函数中支持四个方向的旋转,因此HW的值做了根据参数 dir 做了相应的调整。
调用示例:
CImgShape is;
is.showPerspectiveImage(m_pImgTabDlg->m_myImg, !false, 40, 25, L"R", m_pImgTabDlg->GetDlgItem(IDC_STATIC_IMG2));
(上述边角关系是本人简单推断的结果,并没有参照有关资料,可能会有一些疏漏,但是基本效果经过实际检验,好像是正确的。恳请高手指点)