Cesium深入淺出之視頻投影【轉】


引子

中間有事,耽擱了好久才更新。這一篇要做的是視頻投影,也有視頻投射、視頻融合之類的叫法。本篇內容比較簡單,僅停留在出效果的層面,所以想要高級應用的小盆友可別扔我雞蛋啊,待我日后好好研究一番再來補上。要知道,要做到視頻與模型真正的融合可不是一件簡單的事情,不誇張地說,申請個專利都是沒問題的。現在嘛,入門級實現,先講究看着吧。

預期效果

實現原理

開篇就說了,咱們這篇是入門級的,所以原理非常簡單,用一句話來描述,就是給一個Geometry附上材質,然后貼到地圖上。涉及到的API內容也比較少,MaterialRectangleGraphicsPolygonGraphics,前幾篇也介紹過類似的接口了,就不在贅述了,可以點擊鏈接查看官網API。

具體實現

Video標簽

要把大象放冰箱,第一步你得有大象啊。先插入一個視頻標簽,里面是你的視頻地址,這里我借用一下官網示例里的地址了。

1 <video id="myVideo" muted="" autoplay="" loop="" crossorigin="" controls="">
2     <source src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.webm" type="video/webm">
3     <source src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.mp4" type="video/mp4">
4     <source src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.mov" type="video/quicktime">
5 </video>

我們看到沙箱中給了我們三個地址,分別是三種格式,這里我們推薦使用webm格式,一看這名字就知道它對web支持最好了,實際測試的過程中,其他格式如mp4會有卡頓或延遲的情況出現。

實體容器

大象有了,現在就差個冰箱了。通常情況下我們會使用Rectangle,因為視頻的形狀就是四四方方的嘛。

復制代碼
 1 // 獲取視頻元素
 2 const videoElement = document.getElementById("myVideo");
 3 // 創建實體對象
 4 const rectangle = viewer.entities.add({
 5     rectangle: {
 6         coordinates: Cesium.Rectangle.fromDegrees(-80.0, 39.0, -79.0, 40.0),
 7         material: videoElement
 8     },
 9     // 或創建多邊形
10     // polygon: {
11     //    hierarchy: new PolygonHierarchy(positions),
12     //    material: videoElement
13     // },
14 });
15 // 鎖定實體對象(這句可有可無)
16 viewer.trackedEntity = rectangle;
復制代碼

好了,大功告成了。Waht? 這就好了?是的,這樣就已經把視頻投影到場景中了。哈哈,水了水了,這篇文章真的水,再多寫點有的沒的吧。

時鍾同步

雖然功能已經,但是不要忘了頁面中還掛着那個video呢,那么干掉它吧,設置樣式隱藏誰都會。注意,只能是隱藏,不能刪掉哦,刪掉的話那你場景中的視頻就是無源之水了。

1 videoElement.style.display = 'none';

OK,煩人的畫面不見了,咦,你會驚喜的發現,場景中的視頻怎么不播放了。懷疑是video標簽隱藏的關系,把它再顯示出來,果然視頻又動了。怎么辦?這時候就要用到時鍾同步了。這里使用的是VideoSynchronizer,它可以使視頻元素與Cesium的模擬時鍾同步,下面看下它的構造函數:

名稱 類型 描述
options Object 選項子屬性:
名稱 類型 默認值 描述
clock Clock   用於驅動視頻的時鍾實例。
element HTMLVideoElement   要被同步的視頻元素。
epoch JulianDate Iso8601.MINIMUM_VALUE 標記視頻開始的模擬時間。
tolerance Number 1.0 時鍾和視頻可分離的最大時間量(秒)。
結構很簡單,就是傳入Cesium的時鍾和視頻元素,沒什么好說的,上代碼: 
1 let synchronizer = new Cesium.VideoSynchronizer({
2     clock : viewer.clock,
3     element : videoElement
4 });

 加上這一步之后,再運行代碼試試。矮~矮~怎么視頻還是不動呢,不光如此,就連video標簽里的視頻也不動了。小盆友,別急,不動就對了。原來啊,視頻已經和模擬時鍾同步了,也就是說時鍾動了你視頻才能動啊。哦~恍然大悟,我去打開時鍾。

1 viewer.clock.shouldAnimate = true;

現在再把video便簽隱藏了就完全沒有影響了。

小結

沒有做多深入的研究,注定是就是一篇水文,群里有有伙伴問我怎么調整視頻的形狀,我說很簡單啊,只要改變實體的形狀就可以了,結果啪啪打臉,如圖:

我們看到,改變實體的形狀並不能影響到視頻投影,默認的是按最大邊填充的,多余的都被截掉了。我們知道,實際的監控視頻正射的很少,要想貼合三維模型肯定要做梯形校正的,這是個很實在的問題,后面必須解決掉。現在初步的思路是有的,既然視頻投影就是材質填充,那么在着色器中通過紋理坐標應該能控制紋理的形狀。哦嚯,又立了一個flag,之前的可視域分析還有坑沒填,哎,時間真心不夠啊。

最后,照例來一波宣傳:如果你有什么好的想法,可以給我留言,或者可以加這個群854943530,群的宗旨不追求人多,只追求切實解決問題,真正學到東西。

后記

后來,萬能群友給了個思路,又重新弄了下,大致是參考了可視域分析的效果,還別說,現在真有點投影儀投射影像的感覺了,陰影部分是不會貼圖的,而且垂直邊緣不會出現斷崖式的銜接,看起來很舒服,來看看效果:


免責聲明!

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



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