请问:我在MFC中实现鼠标选定矩形框进行区域缩放,在ONSIZE()中用glOrtho实现了,但是它远近大小都一样,请问用gluPerspective怎么做? 
说明:用glOrtho可以在鼠标选定区域后进行放大再平移到屏幕中央,而gluPerspective总是做得不准确,比如我也是通过计算选定区域到中心的距离,再计算放大倍率,如果三维图不旋转,则可精确达到目标,但是当图形旋转后,那么我鼠标点击到屏幕的那个位置实际上已经不是物体的真实位置,因为物体旋转后深度变了,这样很难保证使物体达到全拼显示我想要的位置的图形,不知道怎么计算这个值。
请各位不吝赐教!如果能解决,我可以多给几十分!

解决方案 »

  1.   

    glscale()不行,它缩小时使整个图形积在一块,因为有光照,使得图形变得非常亮。我试过了。
      

  2.   

    void gluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);利用fovy(The field of view angle, in degrees)来计算,角度的变化就可以产生放大的效果。double value = tan(fovy*MATH_PI/180);
    value = ....;//根据你的比例变化调节
    fovy = atan(value)*180/MATH_PI;是不是你上次还欠我写分数。关于保持图像比例不变的问题。(说笑的)
      

  3.   

    buggycode(风雨寒夜) 的想法我试过了,当把角度设大设小的时候,长条形的物体在角度大缩小物体时看起来很长,因为远处相比于近处小很多,造成视觉效果这样,反之角度小时放大物体使长条形物体看起来很短。
    依然非常感谢buggycode(风雨寒夜)的建议!
      

  4.   

    为了将问题进一步说明清楚,我将部分代码列举如下:
    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坐标显示,这样,就没有精确放大对应倍率!!!
      

  5.   

    其实改变的方法很多,1。改变角度。有你说的问题。
    2。移近物体。(lookat)但是近的物体会消失。移到后面去了
    3。改变ViewPort。(Viewport是一个变化矩阵,不是必须和window的size相同).这个最容易。也就是安现有的投影放大。但是如果再做旋转可能感觉不好(或是计算可能复杂)。所以我没试你都可以试试。