Cesium隨筆:視錐繪制(上)


第一篇CesiumJS技術日記,不管技術難不難,認真歸納是個好習慣。本文繞彎太多,要直接繪制視錐的請移步這里

0.前言

最近在研究視域分析,思路:使用ShadowMap.js接口開放的陰影繪制功能,指定點光源的相關參數。然而在調試的過程中發現並沒有那么簡單,生成ShadowMap對象時會拋出無法在參數中找到Context對象的異常,這個Context對象在Api文檔中並沒有提及,這個問題在https://github.com/AnalyticalGraphicsInc/cesium/issues/4010中提及,Cozzi說不支持,索性視域分析就放一放,先將視錐繪制出來。這里只說關鍵的地方,primitive的加載、鼠標事件等過程就不多說了。

視錐繪制

1.思路

方案1:確定攝像機位置->確定攝像機方向->生成新相機實體->使用lookAt(target,offset)設置相機位置姿態->獲取相機視錐->繪制視錐,該方案應該是標准方法,但是調試過程中繪制的視錐總是出現在地心處,多次嘗試無果(和下漫畫如出一轍):

調試過程

切忌鑽牛角尖,嘗試方案2:

方案2:確定相機位置->確定攝像機方向->生成視錐幾何體->計算視錐俯仰角度->計算視錐航向角度->繪制視錐。方案2相對於前者的難點在於相機姿態的計算,原本使用myCamera.lookAt(target,offset)可以直接計算出視錐的姿態,無奈該方法繪制出錯,現在只能自己算了(筆者沒有找到根據兩點計算姿態的函數)。

2.視錐幾何體

視錐的形態和初始姿態(yaw->0,pitch->0,roll->0)如下圖。

視錐初始姿態

視錐構造參數如下:

視錐構造參數

frustum:視錐本體,下面詳細說明,

origin:軸心,就是那個尖的位置,

orientation:決定相機看的方向,后面再詳細說明,

vertexFormat:該參數和視錐繪制沒有關系,保持默認即可。

frustum參數說明

我們選用PerspectiveFrustum,如下是官方doc的構造函數參數。

構造參數列表

near和far參數作用如下圖,其中虛線是輔助線,不屬於繪制的視錐幾何體。

near&far

fov:查看的視場角,繞z軸旋轉,以弧度方式輸入。

aspectRatio:垂直邊和水平邊的比值,如下圖的aspectRatio為n。

fov&aspectRatio

far,near,fov,aspectRatio四個參數確定了便可以確定視錐的形狀。

3.視錐姿態計算

在程序啟動之后的第一件事是通過鼠標選取兩個點:起點和瞄准的點,通過這兩個點來計算出視錐的姿態,如下圖from點便是視錐的origin,這里我們只關心航向(yaw/heading)和俯仰(pitch)兩個參數,不關心橫滾(roll),我們希望計算出來的航向角和俯仰角通過如下圖的這種方式來表示相機瞄准的方位,下圖中粉色線是視錐所表示相機所發射的射線。即航向角和俯仰角為0時射線指向x軸方向,航向角增加射線繞着z軸順時針轉動,俯仰角增加射線繞着y軸轉動。

計算出的姿態換算成四元素(Quaternion),用作視錐的orientation參數。

姿態角度

不過視錐初始化狀態發射的射線(表示的相機所發射)並不是指向x軸方向,而是指向z方向,且航向沿着x的反方向,將視錐航向角-180°,俯仰角-90°,便是視錐理想的初始姿態。

視錐初試狀態

姿態角度計算

Cesium中的經緯度坐標系和笛卡爾坐標系該選誰呢?上文中提到的姿態所參考的xyz軸是以橢球地表為參考的(x指向正東,y指向正北,z垂直於地面向上),因此選擇經緯度更為直觀,但是只限於短距離的計算。

俯仰角計算,先計算絕對值:

let dist = getSpaceDistance(firstPos, secondPos);//獲取空間距離

let h = getVerticalDistance(firstPos, secondPos);//獲取垂直高度差

let pitchRadian = Math.asin(Math.abs(h / dist));

再根據h的正負判斷俯仰角的正負值(仰為正,俯為負)。

航向角計算,先計算第一象限的值:

let xDist = getNorthwardDistance(firstPos,secondPos);

let yDist = getEastwardDistance(firstPos, secondPos);

let headingRadian = Math.asin(Math.abs(xDist) / Math.sqrt(Math.pow(xDist, 2) + Math.pow(yDist, 2)));

現在判斷To點的位置,結合之前視錐的初始姿態,計算出最終的航向弧度。

case 區域1:

headingRadian = (180.0+ headingRadian * Cesium.Math.DEGREES_PER_RADIAN) / Cesium.Math.DEGREES_PER_RADIAN;

case 區域2:

headingRadian = (360.0- headingRadian * Cesium.Math.DEGREES_PER_RADIAN) / Cesium.Math.DEGREES_PER_RADIAN;

case 區域3:無需操作

case 區域4:

headingRadian = (180.0- headingRadian * Cesium.Math.DEGREES_PER_RADIAN) / Cesium.Math.DEGREES_PER_RADIAN;

當然,這種方法僅僅適用於短距離和靠近赤道的地區,對於筆者的用途足夠了。

4.總結

其實並不推薦這樣的方法來計算視錐(不過好歹筆者調試了半天才試出來,也記錄一下),后面將敘述推薦的方法。

本文轉自 https://www.jianshu.com/p/3be689a9bf3f,如有侵權,請聯系刪除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM