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方法中。

    文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
  • 相关阅读:
    Chrome cookies folder
    Fat URLs Client Identification
    User Login Client Identification
    Client IP Address Client Identification
    HTTP Headers Client Identification
    The Personal Touch Client Identification 个性化接触 客户识别
    购物车 cookie session
    购物车删除商品,总价变化 innerHTML = ''并没有删除节点,内容仍存在
    453
    购物车-删除单行商品-HTMLTableElement.deleteRow()
  • 原文地址:https://www.cnblogs.com/yhlx125/p/3103333.html
Copyright © 2011-2022 走看看