1. 程式人生 > >WebGL——osg框架學習四

WebGL——osg框架學習四

cal nts 再見 組裝 copy class entry tegra 葉子

  這篇我們接著來看一下DrawEntityActor類,我們來看看這個繼承DrawActor的類到底做了什麽事。我們之前學習了Drawable對應的DrawActor,那麽我們類比的來看DrawableEntity對應DrawEntityActor,這樣就好理解一些。首先我們還是先來看DrawEntityActor的構造函數,看看他除了繼承DrawActor以外還有哪些私有成員。下面是DrawEntityActor的構造函數。

 1 /*
 2 繪制對象角色
 3  */
 4 let DrawActor = require(‘./DrawActor‘);
 5 let Geometry = require(‘../core/Geometry‘);
6 let StateSet = require(‘../core/StateSet‘); 7 let RenderEntity = require(‘../scene/RenderEntity‘); 8 let SceneRoot = require(‘../scene/SceneRoot‘); 9 let BoundingBox = require(‘../util/BoundingBox‘); 10 11 let DrawEntityActor = function (renderer) { 12 DrawActor.call(this, renderer); 13 14 this
._currentRenderEntity = undefined;//當前處理的渲染實體,臨時數據 15 this._currentMaterial = undefined;//當前默認顏色狀態,臨時數據 16 this._isEntityMaterial = false;//臨時數據,實體的材質無腦取最上面的節點 17 this._currentBoundingBox = new BoundingBox();//計算RenderEntity包圍盒,臨時數據 18 }; 19 20 DrawEntityActor.prototype = Object.create(DrawActor.prototype);
21 DrawEntityActor.prototype.constructor = DrawEntityActor;

我們首先看到這個構造函數是需要renderer渲染對象作為參數的,其次他是繼承DrawActor類的。他的私有成員有四個,分別是this._currentRenderEntity當前處理的渲染實體;this._currentMaterial當前默認顏色狀態;this._isEntityMaterial當這個標記為false時實體的材質取最上面節點的材質;this._currentBoundingBox渲染實體的包圍盒。

  就這些,其他只要是DrawActor父類原型鏈上包含的成員屬性DrawEntityActor一概包含。   我們來看一下DrawEntityActor的成員函數有哪些,即他獨有的操作是什麽。我們還是老樣子,一個一個來看。

 1 //重載
 2     pushStateSet: function (stateset) {
 3         if (stateset) {
 4             if (this._isEntityMaterial) {
 5                 if (stateset.isMaterialAttribute()) {
 6                     if (this._currentMaterial === undefined) {
 7                         this._currentMaterial = stateset;//無腦取最上面的,實體的顏色狀態是這樣
 8                     }
 9                 } else {
10                     //添加StateGraph子節點,更新當前活動的StateGraph為新的狀態
11                     this._currentStateBin = this._currentStateBin.addStateSetChild(stateset);
12                 }
13             }
14             else {
15                 //添加StateGraph子節點,更新當前活動的StateGraph為新的狀態
16                 this._currentStateBin = this._currentStateBin.addStateSetChild(stateset);
17             }
18         }
19     },

這個是覆蓋了父類原型鏈上的pushStateSet函數,我們很容易可以看到這是修改了當前渲染狀態樹this._currentStateBin上當前渲染實體對應的狀態StateSet節點的狀態,其中討巧的是如果當前狀態為空,就取上級的渲染狀態StateSet。剩下的就是將參數StateSet狀態賦值給當前渲染實體對應的狀態樹上的狀態節點。

  我們接下去看下一個成員函數。

 1 popStateSet: function (stateset) {//重載
 2         if (stateset) {
 3             if(this._isEntityMaterial){
 4                 if (stateset.isMaterialAttribute()) {//幾何級別是最底層,這時才能置空
 5                     if (this._currentMaterial === stateset) {
 6                         this._currentMaterial = undefined;
 7                     }
 8                  } else {
 9                     this._currentStateBin = this._currentStateBin.getParent();
10                 }
11             }else{
12                 this._currentStateBin = this._currentStateBin.getParent();
13             }
14         }
15     },

此函數同樣是重構原型鏈上的popStateSet函數,我們很容易可以看出來這個函數是將特定狀態節點刪除。這裏有一個要特別註意,由於某些繼承上一級狀態的節點的狀態和上級的狀態是相同的,所以必須遍歷到最靠近葉子的節點才能安全刪除。
  好,我們接下去看下一個函數。

 1 pushDrawable: function (geometry) {//重載
 2         let drawable = this.createDrawable();
 3         drawable.setStateBin(this._currentStateBin);
 4         drawable.setGeometry(geometry, this.getCurrentTransformMatrix());
 5         drawable.setRenderEntity(this._currentRenderEntity);
 6         if (this._currentMaterial) {
 7             drawable.setMaterial(this._currentMaterial);
 8         } else {//如果沒有材質,提供一個默認值,非常重要,可以確保不用頻繁的重新加載上級Program
 9             drawable.setMaterial(StateSet.DefaultMaterial);
10         }
11 
12         this._currentBoundingBox.expandByBoundingBox(drawable.getBoundingBox());
13         this.addDrawable(drawable);
14     },

這個函數就包含很多操作了,同樣是重構,所有的操作都是組裝渲染對象drawable。首先組裝狀態樹,接下來組裝geometry幾何體對象,然後裝配renderEntity渲染對象,接下來設置材質material,然後設置包圍盒,最後加入可繪制對象drawable。裝配完成。接下去鯽魚還有介紹幾個函數。

 1 /*
 2 提前遍歷RenderEntity的目的
 3 確認每個drawable的世界坐標變換,確認除RenderEntity外的狀態樹
 4 相機樹基本不用考慮,只有主相機
 5  */
 6 DrawEntityActor.prototype[SceneRoot.typeID] = function (root) {
 7     DrawActor.prototype[SceneRoot.typeID].call(this, root);
 8 
 9     //更新根節點的包圍球
10     this._sceneRoot.getBoundingSphere().expandByBoundingBox(this._sceneRoot.getBoundingBox());
11 };
12 //RenderEntity
13 DrawEntityActor.prototype[RenderEntity.typeID] = function (Rentity) {
14     this._currentStateBin = this._baseState;
15     this._currentRenderEntity = Rentity;
16     this._currentMaterial = undefined;
17     this._isEntityMaterial = true;
18 
19     //這裏RenderEntity的狀態不考慮,RenderEntity的狀態在實時渲染時起作用
20     this.traverse(Rentity);
21 
22     this._isEntityMaterial = false;
23 
24     //直接求得包圍盒
25     let bb = new BoundingBox();
26     bb.copy(this._currentBoundingBox);
27     Rentity.setBoundingBox(bb);
28     this._sceneRoot.getBoundingBox().expandByBoundingBox(Rentity.getBoundingBox());//擴充包圍盒
29 
30     //重置引用,為下次使用準備
31     this._currentRenderEntity = undefined;
32     this._currentMaterial = undefined;
33     this._currentBoundingBox.reset();
34 };
35 //Geometry已經是葉子,不需要繼續遞歸了
36 DrawEntityActor.prototype[Geometry.typeID] = function (geometry) {
37     let stateset = geometry.getStateSet();
38     this.pushStateSet(stateset, true);
39     this.pushDrawable(geometry);
40     this.popStateSet(stateset);
41 };
42 module.exports = DrawEntityActor;

這些是一些工具函數,但都掛在原型上,可見將來都可以用到。好了,今天的DrawEntityActor類就介紹完了,鯽魚謝謝大家陪伴,下周再見。
  本文系原創,如需引用,請註明出處:https://www.cnblogs.com/ccentry/p/10261979.html

WebGL——osg框架學習四