炫酷!快來看看阿里工程師的年會是怎樣辦的?

最近在阿里巴巴內部就掀起這樣一陣“笑容簽到”風潮。在年會開場,大家是這樣排隊刷臉的:

炫酷!快來看看阿里工程師的年會是怎樣辦的?

而刷臉成功後,入場人員的花名、頭像以及“笑容指數”會實時同步顯示在會場大屏幕上,並匯聚成一個“笑臉星球”。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

這是阿里巴巴信息平臺一群90後工程師,用兩週時間開發的一套年會開場秀系統:

觀眾在經過人臉識別後,系統會根據人臉表情特徵,識別出觀眾的花名(名字)與微笑指數,同時吐出一句“評語”。當笑容越燦爛,評價就會越高。同時通過技術手段,這些信息還會上屏展示與互動。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

工程師們在現場調試

不僅是部門年會,在內部一些大型比賽、重要頒獎典禮等活動開場,也逐步用起了這一套科技感滿滿的開場秀。同時根據活動不同主題,還可以進行個性化定製呈現。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

阿里內部一些重要大會陸續使用這套系統開場

背景

傳統大會通常採用的暖場方式是,在大屏幕上循環播放宣傳視頻,等觀眾差不多到齊時,一個321的倒計時宣告開始,既老套又缺乏互動。更是白白錯過一次向觀眾展示公司技術與公司人才的機會。

那有沒有一種可以將科技感與互動感結合的開場秀呢?恰逢新一財年信息平臺部門大會在即,我們想以此為切入點,給大家玩一些不一樣的開場。

解決方案

任何一個“靠譜”的前端工程師,肯定會下意識想用H5動畫來替代視頻。我們的方案是:使用酷炫的H5動畫,並且結合智慧園區團隊的人臉識別技術實現人員掃臉簽到+大屏展示的技術方案。既能運用及展示內部的技術,又能起到不錯的暖場效果。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

根據方案構想,很快就形成了初版需求demo。梳理一下,可以拆分出下面幾點功能:

  • 初始狀態下,是默認做自轉運動的星球,周圍有圍繞的衛星
  • 當人員進場時,人臉識別成功後,在屏幕上展示
  • 展示完之後,照片要飛回到自轉的球面上,跟著球一起做自轉運動
  • 會議開始前,人工控制照片做粒子效果,over

技術方案

當功能拆解後,便是研究怎麼實現方案了。出於對效果考慮,準備選擇3維動畫來創作,並最終採用了Three.js作為3D引擎庫,結合tween.js作為配套的動畫庫,以及基於webpack的腳手架nowa鏈接作為技術支持。

whyThree.js?

目前市面上比較成熟的3D庫有Three.js和Babylon.js,但對比兩者後可發現:

  • Babylon.js常用於製作3d遊戲引擎,傾向於遊戲開發;而Three.js是純渲染引擎。
  • Babylon.js誕生不久(13年),社區活躍;而Three.js相對久一些(比webgl還久),且比較流行,代碼易讀,團隊成員有相關的開發經驗。
  • Babylon.js已經支持了webgl2的多數特性,並且能夠平滑降級;而Three.js還是處於提需求階段,並沒有支持。

所以最後選擇的是Three.js,想嘗試下webgl2.0的小夥伴可以試下Babylon.js。

技術實現

介紹完技術引擎後,接下來將結合整體的功能流程,為大家解析下如何通過技術實現。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

step1:讓球體運動起來

炫酷!快來看看阿里工程師的年會是怎樣辦的?

這是動畫展示效果的第一步。通過Three.js的基本方法,很容易實現在場景中添加對象的功能。如上圖所示,在場景中添加了一個球體,並讓它做順時針的轉動,而讓球表面的圖做逆時針的轉動,並向場景中添加了不斷向z軸負方向運動的星星,和做一定角度的公轉運動的衛星。

炫酷!快來看看阿里工程師的年會是怎樣辦的?

三維座標系中的點座標x,y,z可以轉換成了(上圖)中的極座標r,θ,φ(半徑r和兩個角度θ 和φ),同樣可以用來表示點的位置(反過來也能推導)。

球面上的方片也是由對象構成。人員簽到成功之後,方片上會變成照片,這裡需要事先計算出方片相對於球面的位置以便生成方片。根據前期配置的到場人數n,從而讓球面生成均勻分佈的n個點,得到每個點的極座標系位置,再轉換成點座標位置,這些位置就是方片位置。

step2:加入“微笑”展示效果

炫酷!快來看看阿里工程師的年會是怎樣辦的?

前端通過輪詢定時請求後端接口,來拉取人臉識別數據,展示之後告訴後端已經展示過了。由於現場人臉識別後的“微笑”需要實時展示在主屏上,每場年會活動到場人數不等(約500-1500人),在這一狀況下,如何保證在規定時間內完成人員入場與展示。我們的方案是:展示時間可以動態調節,人流量大時識別成功之後大屏就展示快一些,反之則展示慢一些

因此,需要在前端維護了一個隊列,用於存儲識別成功但還未展示人員,輪詢拉取的數據會進入到隊列中,展示過的數據則會從隊列中移除,一個展示動畫的時長會根據隊列的長度動態調節,取值範圍2.5-5s不等。

step3:讓“微笑”隨球體一起運動

“微笑”展示後,還有個照片飛回球面並跟著球體一起運動的效果。因為牽涉到座標系的相對運動球面的位置是相對於父元素來實現的),這一效果較難實現。

通過step1,可以計算出方片的位置position(position是個三維向量:xyz),因為位置是相對球體的,所以從球體看來方片的位置永遠是xyz,而在全局看來,方片的位置是永遠在變化的,而這個位置座標怎麼獲取是一個問題。

當時,小夥伴們想到了兩種方案:

第一種:讓照片相對球體運動,這樣就不用去考慮方片位置了,因為這個位置是不變的。但這樣的弊端是,因為球體在運動,照片也需要一直運動。如果要達到視覺上看“照片不動”的效果,就需要照片永遠對著攝像頭。

第二種:讓照片相對全局運動,在每一幀的時候去獲取方片相對於全局的座標。然後在這一幀內慢慢趨近於這個座標,最後實現位置的重疊。

經過討論,決定採用第二種方案。因為核心是要解決座標系相對轉換的問題,但第一種方案並沒有解決,只是把問題方式轉移了。還好,Three.js提供了現成的方法:getWorldPosition用於返回表示對象在世界空間中的位置向量。

這樣,就可以得到方片的全局座標。

現在知道了照片的位置和最後需要到達的位置。但如果直接從初始位置向最後位置運動,還會有個問題:照片可能直接穿過球體而達到最後的位置(不符合運動規律),所以這裡需要儘可能做曲線運動,而不是讓照片穿過球體。

我們還是用到了上面的座標系轉極座標系的公式,通過初始的極座標位置(sourceR,sourcePhi,sourceTheta)和目標位置的(targetR,targetPhi,targetTheta)。根據線性差值公式計算出在每一幀中的中間位置(currentR,currentPhi,currentTheta),再轉換成點座標系下的位置,即為每一幀時照片的位置,從軌跡上來看是一個曲線運動,且不會穿過球體。

step4:粒子動畫開場

炫酷!快來看看阿里工程師的年會是怎樣辦的?

終於進入最後的環節了。在活動正式開場前,“笑臉星球“會散開成粒子狀態,通過粒子運動拼成本場活動的主題文案。這裡運用到粒子動畫效果,需要事先知道每個粒子最後運動的位置。我們參考了canvas粒子動畫的效果(具體可以自行查一下),簡化如下:

  1. newImage加載圖片
  2. 用context.drawImage把圖片畫到一張canvas畫布上
  3. 通過context.getImageData就可以獲取畫布上指定區域的像素數據
  4. 比較每個點的像素值就可以記錄下需要像素點的位置信息,轉換成3D的座標
  5. 這邊會涉及座標系的轉換,需要特別注意一下,平面canvas的座標系和THREE.js的座標系是不一樣的)。
  6. 創造粒子,讓粒子做飛散狀運動起來,最後到達指定位置即可
  7. 事先準備兩張圖片,一張白底透明,一張彩色透明,粒子運動完成之後白底漸漸顯示
  8. 然後白底漸隱,彩色的漸漸顯示

性能優化

客觀因素如:大屏分辨率、設備顯卡等不考慮,但需要更多從可控條件來解決部分性能問題。一般衡量動畫是否卡頓用fps衡量,如果在30-60幀之內肉眼基本無感知,再往下,會感受到很明顯的卡頓。第一版開發完成之後,在mac上的幀率只有20+到40。肯定達不到標準,所以從以下幾個方面開始優化。

1.儘量重用Material和Geometry,或者緩存模型;

BufferGeometry 會緩存網格模型,性能要高效點。網格模型生成原理。

  • Geometry 生成的模型是這樣的 (代碼)-> (CUP 進行數據處理,轉化成虛擬3D數據) -> (GPU 進行數據組裝,轉化成像素點,準備渲染) -> 顯示器第二次操作時重複走這些流程。
  • BufferGeometry 生成模型流程 (代碼) -> (CUP 進行數據處理,轉化成虛擬3D數據) -> (GPU 進行數據組裝,轉化成像素點,準備渲染) -> (丟入緩存區) -> 顯示器第二次修改時,通過API直接修改緩存區數據,流程就變成了這樣(代碼) -> (CUP 進行數據處理,轉化成虛擬3D數據) -> (修改緩存區數據) -> 顯示器。

2.減少渲染的對象,或者渲染的時候讓對象不可見:渲染過不再需要的對象可以設置visible = false,或者直接從scene中remove,兩者的區別可以參考Three.js scene.remove vs. visible=false;

3.謹慎地在render()中操作:一般FPS為60也就意味著一秒會執行60次如果render()中有有實例化或是賦值操作很容易會崩潰;

4.選擇合適的對象:粒子我就是用Sprite代替Mesh實現的;

5.考慮光源的影響:會影響場景中對象的渲染;

6.渲染的對象時side屬性儘量用FrontSide,DoubleSide會導致更多的渲染,也是減少渲染的方法;

7.可以用著色器來渲染,用更底層的glsl來實現。

優化完之後的狀態:在mac上基本上都是60fps。保證了最終效果的實現:

炫酷!快來看看阿里工程師的年會是怎樣辦的?

未來規劃

萬萬沒想到,一套專為部門年會做的方案,正逐步演變成一個成熟產品。並且通過可視化、定製化的配置,結合人臉識別技術已經支持集團多個部門的年會與活動。

隨著使用場景的不斷豐富,未來我們還將針對活動主題,在活動過程中增加互動。比如根據入場時的人臉識別,支持抽獎等現場互動,實現年會大屏、觀眾手機、人臉閘機等多屏互動。此外,在面向參會觀眾,還將生成現場圖片等素材,方便收藏。

信息平臺事業部是阿里巴巴經濟體服務的基礎平臺,為阿里巴巴提供生態化、國際化、數據化、移動化以及安全穩定的企業信息服務。我們希望能有更多同學加入,通過技術創新,挑戰自己的不可能,同時為阿里巴巴更多可能性的發生貢獻力量。

訪問:https://job.alibaba.com/zhaopin/positionList.htm?keyWord=JXU0RkUxJXU2MDZGJXU1RTczJXU1M0Yw&_input_charset=UTF-8

即可查看招聘崗位具體信息,投遞簡歷。


每天一篇技術文章,

看不過癮?


分享到:


相關文章: