WebGL——osg框架學習四
這篇我們接著來看一下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框架學習四