乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      3dTiles 幾何誤差詳解

       新進(jìn)小設(shè)計(jì) 2021-11-19

      轉(zhuǎn)載請(qǐng)注明出處。全網(wǎng)@秋意正寒

      1. 瓦片的調(diào)度

      查閱 tileset.json 的規(guī)范,有一個(gè)屬性是 refine,它有兩個(gè)值:"ADD""REPLACE"。

      還有另一個(gè)屬性,叫 geometricError,是一個(gè)數(shù)字。

      "ADD" 的含義是,當(dāng)這一級(jí)瓦片顯示不夠精細(xì)時(shí),渲染下一級(jí)瓦片,這一級(jí)的瓦片保留繼續(xù)顯示(增加下一級(jí)的內(nèi)容)。

      "REPLACE" 的含義是,當(dāng)這一級(jí)瓦片顯示不夠精細(xì)時(shí),渲染下一級(jí)瓦片,這一級(jí)的瓦片被銷(xiāo)毀(被下一級(jí)“替換”)。

      如何衡量這個(gè)“不夠精細(xì)”?

      一個(gè)很簡(jiǎn)單的思路是利用觀察點(diǎn)(也就是相機(jī))到觀察瓦片的距離來(lái)判斷。這個(gè)相機(jī)與瓦片的距離超過(guò)我指定的某個(gè)閾值的時(shí)候,就要渲染下一級(jí)瓦片,而這一級(jí)瓦片則根據(jù) refine 的值進(jìn)行保留或銷(xiāo)毀。

      所謂的 “指定的某個(gè)閾值”,在這里有一個(gè)專(zhuān)有名詞:最大屏幕空間誤差(maximumScreenSpaceError)。

      這個(gè)值是 Cesium3DTileset 類(lèi)中的實(shí)例屬性,默認(rèn)值是16.

      暫且不說(shuō)這個(gè)16的具體含義,先回顧剛才的思路:計(jì)算相機(jī)到瓦片的距離,設(shè)為distance,就能與這個(gè)值進(jìn)行比較了嗎?不是的。

      1.1 屏幕空間誤差(ScreenSpaceError, sse)

      計(jì)算當(dāng)前瓦片的屏幕空間誤差值,才能與 maximumScreenSpaceError 進(jìn)行比較,因?yàn)檫@兩個(gè)才是同一種東西嘛。

      先說(shuō)結(jié)論:屏幕空間誤差(ScreenSpaceError, sse)由幾何誤差、相機(jī)狀態(tài)有關(guān)的各項(xiàng)參數(shù)計(jì)算而來(lái)。

      也就是說(shuō),只要 Cesium 在跑,這個(gè) sse 就是一幀一幀實(shí)時(shí)計(jì)算的,每時(shí)每刻都在計(jì)算。

      查閱 Cesium3DTile 的源碼,不難得知它的計(jì)算方法被定義在 Cesium3DTile 中(可以跳過(guò)代碼不看):

      // Cesium3DTile.js >> Cesium3DTile.prototype.getScreenSpaceError()
      Cesium3DTile.prototype.getScreenSpaceError = function (
        frameState,
        useParentGeometricError,
        progressiveResolutionHeightFraction
      ) {
        var tileset = this._tileset;
        var heightFraction = defaultValue(progressiveResolutionHeightFraction, 1.0);
        var parentGeometricError = defined(this.parent)
          ? this.parent.geometricError
          : tileset._geometricError;
        var geometricError = useParentGeometricError
          ? parentGeometricError
          : this.geometricError;
        if (geometricError === 0.0) {
          // Leaf tiles do not have any error so save the computation
          return 0.0;
        }
        var camera = frameState.camera;
        var frustum = camera.frustum;
        var context = frameState.context;
        var width = context.drawingBufferWidth;
        var height = context.drawingBufferHeight * heightFraction;
        var error;
        if (
          frameState.mode === SceneMode.SCENE2D ||
          frustum instanceof OrthographicFrustum
        ) {
          if (defined(frustum._offCenterFrustum)) {
            frustum = frustum._offCenterFrustum;
          }
          var pixelSize =
            Math.max(frustum.top - frustum.bottom, frustum.right - frustum.left) /
            Math.max(width, height);
          error = geometricError / pixelSize;
        } else {
          // Avoid divide by zero when viewer is inside the tile
          var distance = Math.max(this._distanceToCamera, CesiumMath.EPSILON7);
          var sseDenominator = camera.frustum.sseDenominator;
          error = (geometricError * height) / (distance * sseDenominator);
          if (tileset.dynamicScreenSpaceError) {
            var density = tileset._dynamicScreenSpaceErrorComputedDensity;
            var factor = tileset.dynamicScreenSpaceErrorFactor;
            var dynamicError = CesiumMath.fog(distance, density) * factor;
            error -= dynamicError;
          }
        }
      
        error /= frameState.pixelRatio;
      
        return error;
      };
      

      這么長(zhǎng),其實(shí)在我們關(guān)心的三維模式(即 frameState.mode 為 SceneMode.SCENE3D)下,最核心的只有一句代碼:

      error = (geometricError * height) / (distance * sseDenominator);
      

      其中,

      • error 即計(jì)算得到的 sse 屏幕空間誤差
      • geometricError 即當(dāng)前瓦片設(shè)置好的幾何誤差,寫(xiě)在 tileset.json 中
      • height 即瀏覽器當(dāng)前運(yùn)行著 Cesium 的那個(gè) canvas 的像素高度,如果沒(méi)有自己設(shè)置 progressiveResolutionHeightFraction 值,通常 height 值就是canvas 的像素高度,如果你的 Cesium 占據(jù)了全屏,你的顯示器分辨率是 1920 × 1080,那么這個(gè) height 在你瀏覽器全屏?xí)r,通常是 936 像素。
      • distance 是當(dāng)前狀態(tài)下,攝像機(jī)的世界坐標(biāo)位置到瓦片中心位置的距離,單位是米
      • sseDenominator 是一個(gè)根據(jù)當(dāng)前相機(jī)狀態(tài)下,根據(jù)視錐體的張角(fov)、長(zhǎng)寬比參數(shù)進(jìn)行一系列三角計(jì)算、四則運(yùn)算而來(lái)的一個(gè)參數(shù),具體含義我沒(méi)有深究,但是通常狀態(tài)下,很少會(huì)去修改默認(rèn)相機(jī)的參數(shù),即張角 60 度,寬高比就是 1920÷936(就是canvas的像素寬高比啦),所以這個(gè)值也是固定的,有興趣的讀者可以跟蹤這個(gè)參數(shù)的計(jì)算過(guò)程,還要往里套五六層代碼才知道計(jì)算過(guò)程。它翻譯過(guò)來(lái)就是“sse的分母”。

      2. 推演

      如果不對(duì)相機(jī)進(jìn)行修改,使用默認(rèn)的,而且你的屏幕是1920×1080,恰好你的 canvas 占滿(mǎn)了 body,而且你的瀏覽器是最大化的狀態(tài),那么這個(gè) sseDenominator 的值約為 0.5629165124598852

      顯而易見(jiàn),為了屏蔽屏幕分辨率差異、瀏覽器是否最大化的差異,這個(gè) sseDenominator 的值是會(huì)根據(jù)瀏覽器窗口狀態(tài)、canvas大小以及攝像機(jī)的狀態(tài)進(jìn)行變化的。在此,我們假定就是 0.5629165124598852

      那么 上述代碼改寫(xiě)成:

      \[sse = \frac{geometricError×936}{distance × 0.5629165124598852} \]

      是否還記得一個(gè)參數(shù):maximumScreenSpaceError?它的默認(rèn)值是16

      那么,這個(gè)16就是一個(gè)臨界值,當(dāng) \(sse < defaultMaximumScreenSpaceError = 16\) 時(shí),下一級(jí)瓦片加載,此瓦片根據(jù) refine 進(jìn)行調(diào)整。

      假設(shè) sse 剛好等于16,那么得到一個(gè)二元方程:

      \[16 = \frac{geometricError×936}{distance × 0.5629165124598852} \]

      所以,這個(gè)等式表達(dá)的含義就是,當(dāng)幾何誤差越大(分子變大),要想等式保持相等,那么分母:distance(相機(jī)到瓦片的距離)也應(yīng)變大,變大就意味著——根據(jù) refine 來(lái)控制瓦片的顯隱或增補(bǔ)時(shí),此瓦片觀察距離由此變大。

      所以,這個(gè)幾何誤差是一個(gè)經(jīng)驗(yàn)值。

      下結(jié)論:

      在幾何誤差、相機(jī)狀態(tài)是固定值時(shí),只要觀察距離 > 計(jì)算此幾何誤差的經(jīng)驗(yàn)距離,就會(huì)渲染下一級(jí)瓦片,此瓦片的 refine 規(guī)則若是 REPLACE 則消失,若是 ADD 則保留。
      若渲染下一級(jí)瓦片,則當(dāng)前瓦片的 sse 必定 < maximumScreenSpaceError。

      3. 經(jīng)驗(yàn)值下的幾何誤差計(jì)算

      還是以剛好到臨界值,也即默認(rèn)的 16 時(shí),為例。

      設(shè)定某瓦片距離相機(jī)超過(guò)200米時(shí),該瓦片到達(dá)臨界狀態(tài)。

      代入上式,計(jì)算得到 geometricError 為:

      \[geometricError = 200 × 0.5629165124598852×16÷936=1.9245008972987 \]

      那么現(xiàn)在這個(gè)瓦片的 sse 公式變成了:

      \[sse = \frac{1.9245008972987×936}{distance×0.5629165124598852} \]

      也就是距離越大,sse 越小。當(dāng)距離超過(guò)200米,sse一定小于16,不妨設(shè) refineREPLACE

      在視圖中觀察到小于200米時(shí),此瓦片正常顯示,距離一旦大于200米,該瓦片就被 REPLACE 了,此時(shí)的 sse 肯定也小于16,只需調(diào)整 maximumScreenSpaceError,在 CesiumLab 中叫顯示精度,調(diào)小一些,該瓦片又被顯示了。

      不妨假設(shè)就按 1080p屏幕 + 全屏canvas + 最大化瀏覽器窗口 + 默認(rèn)相機(jī)參數(shù)來(lái)算,列舉常見(jiàn)觀察距離的幾何誤差設(shè)置:

      觀察距離 幾何誤差
      100 0.96225045
      200 1.92450090
      300 2.88675134
      400 3.84900179
      500 4.81125224
      1000 9.62250447
      2000 19.24500897

      觀察不難得知,這是一個(gè)一次函數(shù):

      \[geometricError =f(distance) = distance × 0.5629165124598852×16÷936 \]

      而后面三個(gè)數(shù)字,則與相機(jī)、瀏覽器等因素有關(guān),只要瀏覽器不變,相機(jī)不變,顯示器不變,那么無(wú)論怎么操作視圖,幾何誤差的計(jì)算都只跟經(jīng)驗(yàn)上的觀察距離有關(guān)。

      4. 調(diào)參經(jīng)驗(yàn)

      4.1. 當(dāng)前視角如果不繼續(xù)放大,傾斜攝影的層級(jí)比較低(看起來(lái)模糊)怎么辦

      方案① 調(diào)整最大屏幕空間誤差

      調(diào)大 maximumScreenSpaceError,因?yàn)閹缀握`差不變、距離不變,等式左邊放大,勢(shì)必等號(hào)要變成大于號(hào):

      \[maximumScreenSpaceError > 16 = \frac{geometricError×936}{distance × 0.5629165124598852} \]

      根據(jù)上述結(jié)論,同等條件下最大屏幕空間誤差變大,導(dǎo)致計(jì)算結(jié)果 小于 最大屏幕空間誤差,從而引發(fā)下一級(jí)瓦片渲染,當(dāng)前瓦片執(zhí)行 "refine" 策略。

      方案② 根治法:調(diào)整幾何誤差

      不渲染下一級(jí)瓦片的原因無(wú)非是當(dāng)前幾何誤差所代表的經(jīng)驗(yàn)距離太大了,不小于這個(gè)距離就沒(méi)法渲染。
      解決方法很簡(jiǎn)單,把幾何誤差調(diào)小 即可,參考上文。

      4.2. 想不加載這么快

      同 4.1. 的思路,減小 maximumScreenSpaceError增大 幾何誤差。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多