首頁 > web前端 > H5教程 > 主體

怎麼用H5的WebGL實現3D虛擬機房的漫遊動畫

php中世界最好的语言
發布: 2018-01-30 09:44:36
原創
2429 人瀏覽過

這次帶給大家怎樣用H5的WebGL實現3D虛擬機房的漫遊動畫,用H5的WebGL實現3D虛擬機房的漫遊動畫的注意事項有哪些,下面就是實戰案例,一起來看一下。

第一人稱在3D 中的用法要參考第一人稱在射擊遊戲中的使用,第一人稱射擊遊戲(FPS)是以第一人稱視角為中心圍繞槍和其他武器為基礎的視頻遊戲類型;也就是說,玩家透過主角的眼睛來體驗動作。自從流派開始以來,先進的3D和偽 3D圖形已經對硬體發展提出了挑戰,而多人遊戲已經不可或缺。

現在博物館或公司也經常使用到 3D 動畫做宣傳片等等,3D動畫演繹最大的優勢,便是在於內容與形式上給人的真實感受。它比平面作品更直觀,比 2D 動畫更真實,所以更能給觀賞者以置身於廣告環境當中的感受,大大增強廣告的說服力。 3D 技術的發展甚至挑戰受眾的分辨能力,使受眾的判斷遊離於與虛擬和現實之間。
而且 3D特效的應用為創意提供了更加廣闊的思維空間,並成為創意執行的可靠保證,並豐富了創意的形式和風格手段。根據廣告主題的表現訴求,可以營造出夢幻般的神奇氛圍來刺激打動受眾,從而起到與受眾溝通的目的。
3D動畫宣傳片將3D動畫、特效鏡頭、企業影片、照片、未來前景等內容透過後期合成、配音、解說形成一部直覺、生動、喜聞樂見的高品味的企業廣告宣傳片,讓社會不同層面的人士對企業產生正面的、正面的、良好的印象,從而建立對企業的好感與信任,並信賴該企業的產品或服務。

現在 3D 發展地如此迅速也要感謝人類對於「現實」的追求,所以學好用好 3D 是未來成功必不可少的一部分。

本文例子的想法是進入一個機房參觀,打開門的動作是再生動不過了, 再加上適當地轉彎,基本上完全模擬了人在機房中參觀的效果。還有一個好處就是,如果要示範給領導者看而又不用操作,這種酷炫的效果領導一定會很滿意!

介面上的「reset」和「start」兩個按鈕是直接加在body 體中的button,並在這兩個按鈕上添加點擊事件:

<div></div><div></div>
登入後複製

整個場景由HT 封裝的3D 元件搭建形成的,建構這麼大的場景是需要一定量的程式碼的,為了簡化,我把場景單獨拿出來,並用HT 封裝的ht.JSONSerializer 類別將場景序列化為json,程式碼中只引入了生成後的json 文件,為了讓大家更明確,我這邊做個範例,假設已經搭建好3D 場景了:

dm = new ht.DataModel();g3d = new ht.graph3d.Graph3dView(dm);//.......构建好场景dm.serialize();//可以填入number参数,作为空格缩进值
登入後複製

既然我們已經搭建好環境,轉成了json 文件,程式碼中不好控制,這種情況下我們會將DataModel 資料模型再反序列化,這個函數的功能就是將json 格式轉成對象,並將反序列化的物件傳入到DataModel 資料模型中,詳情請參考HT for Web 序列化手冊:

var g3d = window.g3d = new ht.graph3d.Graph3dView(),   
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 數據模型,獲取這兩個數據:

for (var i = 0; i < dataModel.size(); i++) {   
var data = dataModel.getDatas().get(i);  
 if (data.getName() === "门")
{//json中设置的名称      
window.door = data;   
}   
if (data.getName() === "path")
{       
path = data;   
}   
if (window.door && path)
{//获取到door 和 path 的data之后就跳出循环       
break;  
 }}
登入後複製

這個例子中簡單來說就只有四個動作,“重置”回到原點、“開始動作”、“向前移動”,“停止”。點擊「開始」按鈕,在「開始動作」中我們只做了一個動作,「開門」動作,動作結束之後呼叫「forward」函數向前移動:

function startAnim() {
    
if (window.isAnimationRunning)
{       
return;  
 }   
reset();   
window.isAnimationRunning = true;//动画是否正在进行    ht.Default.startAnim({      
 frames: 30, // 动画帧数,默认采用`ht.Default.animFrames`。       
interval: 20, // 动画帧间隔,默认采用`ht.Default.animInterval`。          
finishFunc: function() {// 动画结束后调用的函数。           
forward();       
},        
action: function(t){ // action函数必须提供,实现动画过程中的属性变化。           
door.setRotationY(-120 * Math.PI / 180 * t);       
}   
});
}
登入後複製

這邊的「reset」函數就是“重置”回到原點的功能,我們通過這個函數將所有變化過的都恢復初始的位置,包括“門”的位置:

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”中前後兩點來設定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)方法,該函數同時改變eye和center的位置,也就是eye和center在兩點建立的向量方向上同時移動相同的偏移。 step為偏移的向量長度值。 firstPersonMode參數為空時則預設採用Graph3dView#isFirstPersonMode()目前值, 如果為第一人稱模式呼叫walk操作,函數會考慮Graph3dView#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]);//把结束点变成起始点           
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 动画结束后调用的函数,并将 window.isAnimationRunning 值设为 false 停止 startAnim 函数。如果不是最后一个点,用户“旋转”之后,回调 forward 函数。至此,全部代码解释完毕,很短的代码量,却做出了这么大的工程!

相信看了这些案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

相关阅读:

手机端怎样用rem+scss做适配

canvas如何实现github404动态

以上是怎麼用H5的WebGL實現3D虛擬機房的漫遊動畫的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!