zoukankan      html  css  js  c++  java
  • [WorldWind学习]17.视域调度(视域体裁剪)

    视域调度(视域体裁剪)

      在WW中用户改变自己的的视角,纹理影像和高程会动态加载,在视野范围内的影像和DEM显示,超出视域范围的瓦片则不显示。不仅是瓦片,太阳、大气网格、三维模型ModelFeature等都会相应的进行剔除。

      看了ROAM相关的的视域体裁剪论文,有好多采用的是将视域体投影的简化算法。WW是否也是这样?我原来以为是,后来在群里和别人聊,说到了Frustum,才知道这个东西的作用。

      这里涉及的类主要是World_Wind_1.4.0_Source\PluginSDK\ViewFrustum.cs文件中的Frustum类。

      查看Frustum类,包含公有字段public Plane[] planes = new Plane[6];可以知道WW的视域裁剪采用的是六面体来实现的。

      1 using System;
      2 using Microsoft.DirectX;
      3 using Microsoft.DirectX.Direct3D;
      4 
      5 namespace WorldWind
      6 {
      7     /// <summary>
      8     /// The region of space in the modeled world that may appear on the screen; it is the field of view of the notional camera.
      9     /// Used to perform culling of invisible object (prior to rendering) to increase speed.
     10     /// See: http://en.wikipedia.org/wiki/Viewing_frustum
     11     /// </summary>
     12     public class Frustum
     13     {
     14         public Plane[] planes = new Plane[6];
     15 
     16         public void Update(Matrix m)
     17         {
     18             //bottom (down) plane
     19             this.planes[0] = new Plane(
     20                 m.M14 + m.M12, //a
     21                 m.M24 + m.M22, //b
     22                 m.M34 + m.M32, //c
     23                 m.M44 + m.M42 //d
     24                 );
     25             
     26             //far plane
     27             this.planes[1] = new Plane(
     28                 m.M14 - m.M13,
     29                 m.M24 - m.M23,
     30                 m.M34 - m.M33,
     31                 m.M44 - m.M43
     32                 );
     33 
     34             //right side plane
     35             this.planes[2] = new Plane(
     36                 m.M14 - m.M11, //a
     37                 m.M24 - m.M21, //b
     38                 m.M34 - m.M31, //c
     39                 m.M44 - m.M41 //d
     40                 );
     41 
     42             //left side plane
     43             this.planes[3] = new Plane(
     44                 m.M14 + m.M11,    //a
     45                 m.M24 + m.M21,    //b
     46                 m.M34 + m.M31,    //c
     47                 m.M44 + m.M41    //d
     48                 );
     49 
     50             //near plane
     51             this.planes[4] = new Plane(
     52                 m.M13,
     53                 m.M23,
     54                 m.M33,
     55                 m.M43);
     56 
     57             //top (up) plane
     58             this.planes[5] = new Plane(
     59                 m.M14 - m.M12, //a
     60                 m.M24 - m.M22, //b
     61                 m.M34 - m.M32, //c
     62                 m.M44 - m.M42 //d
     63                 );
     64 
     65             foreach(Plane p in this.planes)
     66                 p.Normalize();
     67         }
     68 
     69         /// <summary>
     70         /// Test if a sphere intersects or is completely inside the frustum.
     71         /// </summary>
     72         /// <returns>true when the sphere intersects.</returns>
     73         public bool Intersects(BoundingSphere c)
     74         {
     75             foreach(Plane p in this.planes)
     76             {
     77                 float distancePlaneToPoint = p.A * c.Center.X + p.B * c.Center.Y + p.C * c.Center.Z + p.D;
     78                 if(distancePlaneToPoint < -c.Radius)
     79                     // More than 1 radius outside the plane = outside
     80                     return false;
     81             }
     82 
     83             //else it's in view
     84             return true;
     85         }
     86 
     87         /// <summary>
     88         /// Test if a point is inside the frustum.
     89         /// </summary>
     90         /// <returns>true when the point is inside.</returns>
     91         /// <param name="v">XYZ in world coordinates of the point to test.</param>
     92         public bool ContainsPoint(Vector3 v)
     93         {
     94             foreach(Plane p in this.planes)
     95                 if(Vector3.Dot(new Vector3(p.A, p.B, p.C), v) + p.D < 0)
     96                     return false;
     97 
     98             return true;
     99         }
    100 
    101         /// <summary>
    102         /// Tests if the view frustum fully contains the bounding box.
    103         /// </summary>
    104         /// <returns>true when the box is complete enclosed by the frustum.</returns>
    105         public bool Contains(BoundingBox bb)
    106         {
    107             //Code taken from Flip Code Article:
    108             // http://www.flipcode.com/articles/article_frustumculling.shtml
    109             int iTotalIn = 0;
    110             foreach(Plane p in this.planes)
    111             {
    112                 int iInCount = 8;
    113                 int iPtIn = 1;
    114                 // TODO: Modify bounding box and only check 2 corners.
    115                 for(int i = 0; i < 8; i++)
    116                 {
    117                     if(Vector3.Dot(new Vector3(p.A,p.B,p.C), bb.corners[i]) + p.D < 0)
    118                     {
    119                         iPtIn = 0;
    120                         --iInCount;
    121                     }
    122                 }
    123 
    124                 if(iInCount == 0)
    125                     return false;
    126 
    127                 iTotalIn += iPtIn;
    128             }
    129 
    130             if(iTotalIn == 6)
    131                 return true;
    132 
    133             return false;
    134         }
    135 
    136         /// <summary>
    137         /// Tests if the bounding box specified intersects with or is fully contained in the frustum.
    138         /// </summary>
    139         /// <returns>true when the box intersects with the frustum.</returns>
    140         public bool Intersects(BoundingBox bb)
    141         {
    142             foreach(Plane p in this.planes)
    143             {
    144                 Vector3 v = new Vector3(p.A,p.B,p.C);
    145                 bool isInside = false;
    146                 // TODO: Modify bounding box and only check 2 corners.
    147                 for(int i = 0; i < 8; i++)
    148                 {
    149                     if(Vector3.Dot(v, bb.corners[i]) + p.D >= 0)
    150                     {
    151                         isInside = true;
    152                         break;
    153                     }
    154                 }
    155 
    156                 if(!isInside)
    157                     return false;
    158             }
    159 
    160             return true;
    161         }
    162     
    163         public override string ToString()
    164         {
    165             string res = string.Format("Near:\n{0}Far:\n{1}", planes[4], planes[1] );
    166             return res;
    167         }
    168     }
    169 }

    该类实现的方法主要包括下面5个,后面四个主要是进行相交检测和包含检测:

    public void Update(Matrix m);

    public bool Intersects(BoundingSphere c);

    public bool ContainsPoint(Vector3 v);

    public bool Contains(BoundingBox bb);

    public bool Intersects(BoundingBox bb);

    调用了Frustum对象的类其实不多,不过Frustum的重要程度和CameraBase捆绑在一起。

      QuadTileSet类中的调用方式主要是通过调用camera.ViewFrustum来获取并进行相关的判断。在QuadTileSet中总共有3处地方可以查见camera.ViewFrustum,一个是在Update方法中,一个是在GetClosestDownloadRequest,还有一个是在ResetCacheForCurrentView方法中。

      QuadTile类中调用方式通过调用camera.ViewFrustum实现,主要在在Update方法中和Render方法中。

    文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
  • 相关阅读:
    Qt——QLineEdit使用总结
    qt中的lineEdit文本输入框的输入类型限制(三种验证类)
    qt 创建线程
    linux 安装和卸载软件
    c 结构体中的变长数组
    Qt之QSS(QDarkStyleSheet)
    Qt之QSS(Q_PROPERTY-原始属性)
    Qt之QSS(Q_PROPERTY-自定义属性)
    Qt之QSS(白色靓丽)
    Qt之QSS(样式表语法)
  • 原文地址:https://www.cnblogs.com/yhlx125/p/3103333.html
Copyright © 2011-2022 走看看