请问:我在MFC中实现鼠标选定矩形框进行区域缩放,在ONSIZE()中用glOrtho实现了,但是它远近大小都一样,请问用gluPerspective怎么做?
说明:用glOrtho可以在鼠标选定区域后进行放大再平移到屏幕中央,而gluPerspective总是做得不准确,比如我也是通过计算选定区域到中心的距离,再计算放大倍率,如果三维图不旋转,则可精确达到目标,但是当图形旋转后,那么我鼠标点击到屏幕的那个位置实际上已经不是物体的真实位置,因为物体旋转后深度变了,这样很难保证使物体达到全拼显示我想要的位置的图形,不知道怎么计算这个值。
请各位不吝赐教!如果能解决,我可以多给几十分!
说明:用glOrtho可以在鼠标选定区域后进行放大再平移到屏幕中央,而gluPerspective总是做得不准确,比如我也是通过计算选定区域到中心的距离,再计算放大倍率,如果三维图不旋转,则可精确达到目标,但是当图形旋转后,那么我鼠标点击到屏幕的那个位置实际上已经不是物体的真实位置,因为物体旋转后深度变了,这样很难保证使物体达到全拼显示我想要的位置的图形,不知道怎么计算这个值。
请各位不吝赐教!如果能解决,我可以多给几十分!
value = ....;//根据你的比例变化调节
fovy = atan(value)*180/MATH_PI;是不是你上次还欠我写分数。关于保持图像比例不变的问题。(说笑的)
依然非常感谢buggycode(风雨寒夜)的建议!
void CMy3DSLoaderView::OnSize(UINT nType, int cx, int cy)
{
glViewport(0,0,cx,cy);
aspect_ratio = (GLdouble)cx/(GLdouble)cy;
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
gluPerspective(fovyangle,aspect_ratio,nearpt,farpt);
::glMatrixMode(GL_MODELVIEW);
::glLoadIdentity(); CView::OnSize(nType, cx, cy);
}
//////////////////////////////////////////////////////////
// 场景绘制与渲染
//////////////////////////////////////////////////////////
BOOL CMy3DSLoaderView::RenderScene()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glPushMatrix();
//(-camz)<0表示将相机移出屏幕,或者将物体移入屏幕更多,即物体与相机距离拉大,物体显得更小
//xmove为正,表示将物体右移;ymove为正表示将物体上移
glTranslatef(xmove,ymove,-camz); //鼠标旋转
glRotatef( sceneRot[0], 1.0F, 0.0F, 0.0F );
glRotatef( sceneRot[1], 0.0F, 1.0F, 0.0F );
glRotatef( sceneRot[2], 0.0F, 0.0F, 1.0F ); DrawObject();//绘制对象
glPopMatrix(); SwapBuffers(m_pDC->GetSafeHdc());
return TRUE;
}void CMy3DSLoaderView::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture( );//左键抬起,设置无效
mouseleftdown = FALSE;
CRect rect;
GetClientRect(&rect);//rect为屏幕大小 if((m_flag==RECT_ZOOM)&&rect.PtInRect(point))//区域缩放
{
CRect rc, rs;
CClientDC dc(this);
GetClientRect(&rc); //rc为屏幕大小
rs.SetRect(m_RectZoomOldpoint, point);//rs为鼠标选取的缩放框大小
if(rs.Width()==0 || rs.Height()==0)
return;//当选取的缩放框大小为0,观察窗口无穷小,物体放大到无穷大,跳出。 //先平移到屏幕中心
float deta =camz*tan(half_fovyangle)*2/float(rc.Height());//计算实际每个像素相当于平移函数平移的距离对应
m_fstepx = (float(rc.Width())/2-float(rs.Width())/2-float(rs.left))*deta;//rs.left和rs.top的零点在窗口左上角!!!
m_fstepy = (float(rc.Height())/2-float(rs.Height())/2-float(rs.top))*deta;
xmove += m_fstepx;
ymove -= m_fstepy;
//再放大对应比例,实际是移动摄像机与物体的距离来实现放大
//观察窗口大小占窗口大小的比例,百分数。比值越小,观察范围越狭小,显得物体越大
float rs_value = float(rs.Width())/float(rc.Width());//鼠标矩形框的宽度与窗口宽度比(<1)
float rc_value = float(rs.Height())/float(rc.Height());//鼠标矩形框的高度与窗口高度比(<1)
m_scale = (rs_value>rc_value)?rs_value:rc_value;//取宽比和高比两者的最大值
camz=camz*m_scale;
// camz=camz>1 ? camz : 1;
// camz=camz<2000 ? camz : 2000;//优化!!!
OnSize(SIZE_RESTORED, int(rc.Width()), int(rc.Height()));//rc还是窗口的尺寸,不变,只不过ONSIZE此时不会自动调用,所以在这里要写出来。
Invalidate(FALSE);
UpdateWindow();
}
CView::OnLButtonUp(nFlags, point);
}用上述方法存在一个问题:当物体旋转后不知道物体的当前深度或者说比如物体旋进屏幕中,鼠标框选矩形不知道其当前深度信息,放大的比例依然按照中心没有旋转的那点对应的camz坐标显示,这样,就没有精确放大对应倍率!!!
2。移近物体。(lookat)但是近的物体会消失。移到后面去了
3。改变ViewPort。(Viewport是一个变化矩阵,不是必须和window的size相同).这个最容易。也就是安现有的投影放大。但是如果再做旋转可能感觉不好(或是计算可能复杂)。所以我没试你都可以试试。