zoukankan      html  css  js  c++  java
  • 球面相机旋转

    旋转作为三维开发的基本功能,在任何3D程序中都需要。用户通过旋转来实现对模型各个面的浏览,形成直观印象。

    球面相机旋转

    这种旋转方式用户体验方式要优于x轴y轴混合旋转方式,模型旋转的方向和鼠标移动方向保持一致。

    下面给出一种“球面相机”实现旋转的方法。

    原理:

    移动鼠标时,通过gluLookAt来改变视点的位置(采用增量的方式),而模型保持不动。即:只进行视点变换,不进行模型变换。

    下图是用户按下左键,在屏幕上移动的一段距离(从A移动到B)。

    由于屏幕坐标y轴向下,为了与投影平面坐标系(传统笛卡尔坐标)保持一致。

    AM = y1-y2;  /*在消息代码中进行描述*/

    BM = x2-x1;

    建立屏幕和投影变换近裁截面之间的对应关系(如下图)。

    代码实现:

    1 void setSphereCameraPos()
    2 {
    3 // 左键未按下,直接返回
    4  if (!is_left_button_down)
    5 return;
    6
    7 // 从聚焦点指向视点的向量 OA向量
    8   vector3dd a(eye-target);
    9
    10 // 计算球面相机半径
    11   radius = a.getLength();
    12
    13 // 将其单位化
    14   a.normailize();
    15
    16 // 当前相机向上方向与a做叉乘,计算投影面水平向右方向向量u
    17   vector3dd u = upvector.crossProduct(a);
    18 // 将其单位化
    19   u.normailize();
    20
    21 // 计算相机向上方向在投影面上的投影向量 即垂直向上的方向向量v
    22   vector3dd v = a.crossProduct(u);
    23 // 将其单位化
    24   v.normailize();
    25
    26 // 计算屏幕AB在投影面上对应的向量 AB向量
    27   vector3dd m = u*delta_point.x + v*delta_point.y;
    28
    29 // 计算m向量的长度
    30  double len = m.getLength();
    31 // 降低灵敏度
    32   len /=20.0;
    33
    34 if (len>0.0)
    35 {
    36 // 角度AOB 弧度表示 弧长/半径
    37  double x = len/radius;
    38 // 将AB向量单位化
    39   m.normailize();
    40
    41 // 按相反方向转动视点到C 从而使得按与鼠标移动一致的方向转动模型
    42   x =-1*x;
    43 // 计算新的相机位置 C
    44   eye = target+(a*cos(x) + m*sin(x))*radius;
    45
    46 // 计算新的相机向上方向
    47   upvector = v;
    48 }
    49 }

    消息代码

    1 LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
    2   UINT uMsg, // Message For This Window
    3   WPARAM wParam, // Additional Message Information
    4   LPARAM lParam) // Additional Message Information
    5  {
    6 switch (uMsg) // Check For Windows Messages
    7   {
    8 case WM_LBUTTONDOWN:
    9 {
    10 is_left_button_down =true;
    11 pre_point.x = LOWORD(lParam);
    12 pre_point.y = HIWORD(lParam);
    13
    14 return0;
    15 }
    16
    17 case WM_MOUSEMOVE:
    18 {
    19 if (is_left_button_down)
    20 {
    21 cur_pt.x = LOWORD(lParam);
    22 cur_pt.y = HIWORD(lParam);
                // delta_point为增量点
    23 delta_point.x =cur_pt.x-pre_point.x);
                // 保持屏幕坐标系和投影平面坐标系一致
    24 delta_point.y = -1*(cur_pt.y-pre_point.y);
                // 将当前点赋值给前一个点
    25 pre_point = cur_pt;
    26 
    // 计算相机新的位置
    27 setSphereCameraPos();
    28 }
    29
    30 return0;
    31 }
    32
    33 case WM_LBUTTONUP:
    34 {
    35 is_left_button_down =false;
    36 return0;
    37 }
    38 }
    39
    40 // Pass All Unhandled Messages To DefWindowProc
    41  return DefWindowProc(hWnd,uMsg,wParam,lParam);
    42 }
    43  

    vector3dd类

    vector3dd

    效果图:

  • 相关阅读:
    Sitecore 9 介绍
    Sitecore个性化
    Sitecore个性化
    Sitecore A / B测试
    Sitecore性化
    cesium结合geoserver利用WFS服务实现图层编辑(附源码下载)
    leaflet地图全图以及框选截图导出功能(附源码下载)
    openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)
    arcgis api 4.x for js扩展MapImageLayer支持图片图层加载
    cesium结合geoserver利用WFS服务实现图层删除(附源码下载)
  • 原文地址:https://www.cnblogs.com/kekec/p/1793309.html
Copyright © 2011-2022 走看看