基於HTML5和WebGL的碰撞測試

這是公司大神寫的一個放官網上給用戶學習的例子,我一開始真的不知道這是在幹嗎,就只是將三個形狀圖元組合在一塊兒,而後能夠同時旋轉、放大縮小這個三個圖形,點擊「Animate」就能讓中間的那一個圖元單獨繞着某一個點旋轉,表單最上方的「Axis」真的徹底不知道拿來幹嗎用的,以爲好累贅,並且是官網的demo,也沒有解釋。。。因此我今天得任務就是徹底剖析這個例子!!html

本文例子:http://www.hightopo.cn/demo/3drotate/3d-rotate.html node

首先讓咱們來看下這個案例:app

咱們來看看如何操做這個3d交互模型,能夠直接滑動「Rotation」的滑動條,你會看到3d和左下角的2d上的圖元都會旋轉,接着點擊「Axis」中的任意一個值,而後點擊「Animate」,你會看到中間這個圖元會旋轉,同時滑動「Range」的滑動條,這是控制你旋轉的幅度的,若是你調到「0」,那麼就不會旋轉,調到「30」就會旋轉30度,以此類推。接着調整「Reset」你會發現,不是徹底刷新這個界面,而是局部刷新兩邊的圓柱,根據這兩個圓柱與中間節點之間的關聯而重置的。ide

左下角的是整個3d場景內的俯視圖,這樣咱們能夠很是直觀地看清圖元的移動方向和位置。函數

可能你會好奇這個是怎麼俯視圖是怎麼放上去的?若是3d中的圖元變化,這個俯視圖中的圖元也會跟着變化麼?如何把右上角的form表單和左下角的視圖又是怎麼放的?如何只移動3d二把這兩個固定在這邊?或者你可能還有別的問題,在這裏我會盡可能清楚地解答,實在找不到答案能夠去咱們的官網HT for Web查找你的問題。佈局

好了,基礎就是先佈局,布3d場景,HT在提供方法方面算是很是細緻的了,平時咱們生成網格可能就要花費一段時間,又是基礎代碼,新手開發人員都能很快上手呢~短短几行代碼就能建立一個3d場景,簡直太快。。。學習

dm = new ht.DataModel();
g3d = new ht.graph3d.Graph3dView(dm);
g3d.setGridVisible(true);//設置網格可視
g3d.setGridSize(m);//設置網格大小
g3d.setGridGap(w);//設置網格間距
g3d.setEye([-200, 150, 200]);//設置camera位置
g3d.getView().className = 'main';
document.body.appendChild(g3d.getView());

因爲HT默認將全部組件都設置了style「position:absolute」,因此當咱們初始化這個組件以後,必定要在style中寫上位置,而且將這個組件添加進你想要添加進的標籤中,這個例子中,form表單、2d組件和3d組件都互不依附,因此咱們直接將這三個都添加進body中便可,還有一點值得注意的,全部HT組件的最根層都是一個div,是經過組件的getView()函數得到的。因此咱們若是要添加進HTML標籤中,確定也要是HTML標籤才行。測試

而後再界面的右上角放上form表單,放到右上角就直接設置style中的「top」「bottom」「left」「right」便可,2d圖同理:動畫

formPane = new ht.widget.FormPane();
formPane.setLabelAlign('right');
formPane.getView().className = 'formpane';
document.body.appendChild(formPane.getView());
formPane.addRow(['Rotation:', {
    id: 'rotation',
    slider: {
        min: -180,
        max: 180,
        value: 0,
        step: 1,
        onValueChanged: function(e){
            node.setRotation(this.getValue() * Math.PI / 180);
        }
    }
}], [60, 0.1]);

由於這個例子的form表單中的行數和內容比較多,因此我這邊就只取了一個form表單自定義行的例子。這邊的「id」只是爲了能快速查找到這個元素,slider是HT form表單自定義的一個方法,滑動條功能,設置了該屬性後HT將根據屬性值自動構建ht.widger.Slider對象,具體參數能夠參考HT for Web表單手冊ui

至於左下角的2d俯視圖,這是經過跟3d共享同一個datamodel數據模型,只要咱們繪製好了圖形,而後添加進datamodel中去,不論是什麼組件,只要調用了這個datamodel的均可以擁有datamodel中的全部數據:

g2d = new ht.graph.GraphView(dm);
g2d.getView().className = 'g2d';
g2d.setEditable(true);
document.body.appendChild(g2d.getView());
ht.Default.callLater(g2d.fitContent, g2d, [true, 50, true]);

ht.Default.callLater(func, scope, args, delay)獲取全局下一個編號,其中 func指的是回調函數,scope指的是函數域,args指的是函數參數列表,delay則是延遲時間(毫秒)。這個函數能夠在頁面打開時回調g2d.fitContent函數,而後做用域僅在g2d中,這個函數參數列表是fitContent(anim, padding, notZoomIn)函數的參數,這三個參數分別表明「是否使用動畫」,「縮放後圖元區域與拓撲邊緣的距離」,以及「是否將最小縮放值限定爲1」。

接着將3d中的圖元添加進去,這裏我不截取所有代碼,只取一個比較特別的有趣的圖元,中間外層的透明圖元:

shape = new ht.Shape();
shape.s({ 'all.reverse.cull': true, 'all.color': 'rgba(0, 255, 0, 0.5)', 'all.transparent': true });
shape.setThickness(2);
dm.add(shape); var resetShape = function() { var cs = node.getCorners(10, 10);
    cs.push(cs[0]);
    shape.setPoints(cs);
    g3d.setBoundaries(ht.Default.toBoundaries(cs));
};
resetShape();

這邊比較有趣的有幾點:

  1. 這邊用了node.getCorners()這個方法,這個是獲取四個點,對於2d來講就是左上、右上、右下、左下四個點;對於3d來講就是直接獲取底面的四個「左上、右上、右下、左下」點,這個我反應了好一下子才反應過來。。。並以這四個點爲基礎做爲shape的points。
  2. 這邊還用了setBoundaries(boundaries)函數,借用ht.Default.toBoundaries函數來將不符合setBoundaries函數參數的格式轉換成它須要的參數格式。雖然我認爲這一行在這個例子中沒有什麼做用,可是仍是讓我好好學習了一把碰撞測試。

咱們在碰撞測試的時候常常要設置g3d.setNear函數,我實在沒搞懂這個函數是拿來幹嗎的,結果這個例子讓我注意到,若是「我」的視線的近端截面位置也就是setNear(1),那麼我能看到的就是比表面跟進1的距離,這個函數默認設置爲10,就算咱們不設置這個值咱們也能在3d中看到圖元的內部去,剛剛咱們介紹的getCorners()函數,其實它還有兩個參數xpadding和ypadding,分別表明「水平方向padding」「垂直方向padding」,也就是說,在咱們獲取四個角的同時,咱們還能設置這四個角和邊之間的padding。只要將這個值設置得比setNear設置的大,咱們就不會看到3d圖元的內部中去了。

咱們還注意到彷佛是「廢代碼」的一行: cs.push(cs[0])。這個徹底不是廢代碼啊,幫了很大忙呢!在HT中,用ht.Shape建立的圖元,只要你不手動設置繪製關閉,那麼就會停留在你最終繪製的位置,因此我把最後的一個點又和第一個點連起來,那麼就是一個封閉的圖形了,不然你會看到後面缺了一部分,像這樣:

我在其餘文章中也提到過HT封裝了一些很方便的方法和事件,好比datamodel#md,監聽數據的屬性的變化,這邊咱們用了md方法來判斷只有中間這個node可以繞着一個點旋轉,具體參考HT for Web數據模型手冊

dm.md(function(e){ if(e.data === node){ if(e.property === 'rotation'){
            formPane.v('rotation', 180 / Math.PI * e.newValue);
        }
        resetShape();
    }
});

這邊我想要說一下「繞着一個點旋轉」的功能,這邊沒有用咱們自定義的anchor錨點,可是功能相似,經過獲取我form表單上選擇的「left、right、front、back」來設置旋轉中心點,HT中form表單經過getValue(id)簡寫成v(id)根據id獲取對應item元素值:

formPane.addRow([
    {
         button: {
             label: 'Animate',
             onClicked: function(){ var dx = 0,
                 dy \= 0,
                 range = formPane.v('range') * Math.PI / 180; if(formPane.v('left')){
                     dx = -node.getWidth()/2;
 } if(formPane.v('right')){
                     dx = node.getWidth()/2;
 } if(formPane.v('back')){
                     dy = -node.getHeight()/2;
 } if(formPane.v('front')){
                     dy = node.getHeight()/2;
 }
                 animate(node, range, dx, dy);
             }
         }
     },
     {
         button: {
             label: 'Reset',
             onClicked: function(){
                 node.setRotation(0);
             }
         }
     }
], [0.1, 0.1]);

看到這邊你仍是沒懂?快去咱們官網上從beginners重頭開始學習吧!

相關文章
相關標籤/搜索