您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關(guān)如何實現(xiàn)基于HTML5的WebGL經(jīng)典3D虛擬機房漫游動畫,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
第一人稱在 3D 中的用法要參考第一人稱在射擊游戲中的使用,第一人稱射擊游戲(FPS)是以第一人稱視角為中心圍繞槍和其他武器為基礎(chǔ)的視頻游戲類型;也就是說,玩家通過主角的眼睛來體驗動作。自從流派開始以來,先進的3D和偽 3D圖形已經(jīng)對硬件發(fā)展提出了挑戰(zhàn),而多人游戲已經(jīng)不可或缺。
Doom的截圖,這個流派的突破游戲之一,展示了第一人稱射擊游戲的典型視角
現(xiàn)在博物館或者公司也經(jīng)常使用到 3D 動畫做宣傳片等等,3D動畫演繹最大的優(yōu)勢,便是在于內(nèi)容與形式上給人的真實感受。它比平面作品更直觀,比 2D 動畫更真實,所以更能給觀賞者以置身于廣告環(huán)境當中的感受,大大增強廣告的說服力。3D 技術(shù)的發(fā)展甚至挑戰(zhàn)受眾的分辨能力,使受眾的判斷游離于與虛擬和現(xiàn)實之間。
而且 3D特效的應(yīng)用為創(chuàng)意提供了更加廣闊的思維空間,并成為創(chuàng)意執(zhí)行的可靠保證,并豐富了創(chuàng)意的形式和風(fēng)格手段。根據(jù)廣告主題的表現(xiàn)訴求,可以營造出夢幻般的神奇氛圍來刺激打動受眾,從而起到與受眾溝通的目的。
3D動畫宣傳片將 3D動畫、特效鏡頭、企業(yè)視頻、照片、未來前景等內(nèi)容通過后期合成、配音、解說形成一部直觀、生動、喜聞樂見的高品位的企業(yè)廣告宣傳片,讓社會不同層面的人士對企業(yè)產(chǎn)生正面的、積極的、良好的印象,從而建立對企業(yè)的好感與信任,并信賴該企業(yè)的產(chǎn)品或服務(wù)。
現(xiàn)在 3D 發(fā)展地如此迅速也要感謝人類對于“現(xiàn)實”的追求,所以學(xué)好用好 3D 是未來成功必不可少的一部分。
本文例子的思路是進入一個機房參觀,打開門的動作是再生動不過了, 再加上適當?shù)剞D(zhuǎn)彎,基本上完全模擬了人在機房中參觀的效果。還有一個好處就是,如果要演示給領(lǐng)導(dǎo)看而又不用操作,這種炫酷的效果領(lǐng)導(dǎo)一定會很滿意!
http://www.hightopo.com/demo/room-walkthrough/index.html
界面上的“reset”和“start”兩個按鈕是直接加在 body 體中的 button,并在這兩個按鈕上添加點擊事件:
<div></div><div></div>
整個場景由 HT 封裝的 3D 組件搭建形成的,構(gòu)造這么大的場景是需要一定量的代碼的,為了簡化,我把場景單獨拿出來,并用 HT 封裝的 ht.JSONSerializer 類將場景序列化為 json,代碼中只引入了生成后的 json 文件,為了讓大家更明確,我這邊做個示例,假設(shè)已經(jīng)搭建好 3D 場景了:
dm = new ht.DataModel();g3d = new ht.graph4d.Graph4dView(dm);//.......構(gòu)建好場景dm.serialize();//可以填入number參數(shù),作為空格縮進值
既然我們已經(jīng)搭建好環(huán)境,轉(zhuǎn)成了 json 文件,代碼中不好控制,這種情況下我們會將 DataModel 數(shù)據(jù)模型再反序列化,這個函數(shù)的功能就是將 json 格式轉(zhuǎn)成對象,并將反序列化的對象傳入到 DataModel 數(shù)據(jù)模型中,詳情請參考HT for Web 序列化手冊:
var g3d = window.g3d = new ht.graph4d.Graph4dView(), dataModel = g3d.dm(), view = g3d.getView(), path = null;g3d.setMovableFunc(function(data) { return false;}); g3d.setVisibleFunc(function(data) { if (data.getName() === "path") { return false; } return true;}); g3d.setEye([523, 5600, 8165]);g3d.setFar(60000);dataModel.deserialize(json);
我們目前需要操作場景中的“門”、以及我們將要走的路線“path”,遍歷 DataModel 數(shù)據(jù)模型,獲取這兩個數(shù)據(jù):
for (var i = 0; i < dataModel.size(); i++) { var data = dataModel.getDatas().get(i); if (data.getName() === "門") {//json中設(shè)置的名稱 window.door = data; } if (data.getName() === "path") { path = data; } if (window.door && path) {//獲取到door 和 path 的data之后就跳出循環(huán) break; }}
這個例子中簡單來說就只有四個動作,“重置”回到原點、“開始動作”、“向前移動”,“停止”。點擊“開始”按鈕,在“開始動作”中我們只做了一個動作,“開門”動作,動作結(jié)束之后調(diào)用“forward”函數(shù)向前移動:
function startAnim() { if (window.isAnimationRunning) { return; } reset(); window.isAnimationRunning = true;//動畫是否正在進行 ht.Default.startAnim({ frames: 30, // 動畫幀數(shù),默認采用`ht.Default.animFrames`。 interval: 20, // 動畫幀間隔,默認采用`ht.Default.animInterval`。 finishFunc: function() {// 動畫結(jié)束后調(diào)用的函數(shù)。 forward(); }, action: function(t){ // action函數(shù)必須提供,實現(xiàn)動畫過程中的屬性變化。 door.setRotationY(-120 * Math.PI / 180 * t); } }); }
這邊的“reset”函數(shù)就是“重置”回到原點的功能,我們通過這個函數(shù)將所有變化過的都恢復(fù)初始的位置,包括“門”的位置:
function reset() { if (window.isAnimationRunning) { return; } g3d.setCenter([0,0,0]); g3d.setEye([523, 5600, 8165]); window.forwardIndex = 0; door.setRotationY(0);}
要“移動”,肯定需要走路的“路徑”,也就是我們剛剛獲取到的“path”,通過window.points = path.getPoints()._as; 獲取“path”中的所有元素,初始化window.forwardIndex = 0; 通過控制“path”中前后兩點來設(shè)置 3D 場景中的 Eye 和 Center,這樣就能營造一個我們是第一人的效果:
var point1 = points[forwardIndex], point2 = points[forwardIndex + 1];var distanceX = (point2.x - point1.x), distanceY = (point2.y - point1.y), distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY)-200;//兩點之間的距離通過三角形勾股定理計算 怕碰墻所以-200g3d.setEye([point1.x, 1600, point1.y]);//眼睛g3d.setCenter([point2.x, 1600, point2.y]);//我
HT 中 3D 組件有一個 walk(step, anim, firstPersonMode)方法,該函數(shù)同時改變eye和center的位置,也就是eye和center在兩點建立的矢量方向上同時移動相同的偏移量。step為偏移的矢量長度值。firstPersonMode參數(shù)為空時則默認采用Graph4dView#isFirstPersonMode()當前值, 如果為第一人稱模式調(diào)用walk操作,該函數(shù)會考慮Graph4dView#getBoundaries()邊界限制。
g3d.walk(distance, { frames: 50, interval: 30, easing: function(t) {return t; }, finishFunc: function() { forwardIndex += 1; if (points.length - 2 > forwardIndex) {//points.length = 5 g3d.setCenter([point2.x, 1600, point2.y]);//把結(jié)束點變成起始點 g3d.rotate(Math.PI / 2, 0, { frames: 30, interval: 30, easing: function(t) {return t;}, finishFunc:function() { forward();} }); } else { var lastPoint = points[points.length - 1];//json 中path的points 的最后一個點 g3d.setCenter([lastPoint.x, 1400, lastPoint.y]); g3d.rotate(-Math.PI / 2, 0, { frames: 30, interval: 30, finishFunc: function() { window.isAnimationRunning = false; } }); } }});
不管“path”的點有多少個,這個判斷語句還是能運作,只在最后一個點是跳出 finishFunc 動畫結(jié)束后調(diào)用的函數(shù),并將 window.isAnimationRunning 值設(shè)為 false 停止 startAnim 函數(shù)。如果不是最后一個點,用戶“旋轉(zhuǎn)”之后,回調(diào) forward 函數(shù)。至此,全部代碼解釋完畢,很短的代碼量,卻做出了這么大的工程!
關(guān)于“如何實現(xiàn)基于HTML5的WebGL經(jīng)典3D虛擬機房漫游動畫”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。