接着前一篇《WebGL實現sprite精靈效果的GUI控件》,咱們繼續開發咱們的數字系統GUI控件,由於這套數字系統是基於sprite效果的,因此數字隨相機轉動而旋轉(永遠面對相機),隨場景縮放而逆向縮放(數字在屏幕上看上去大小不變)。實現sprite效果的核心方法在前一篇文章裏已經詳細說明,這裏再也不贅述,本文要討論的是如何將用戶輸入的數字文本轉變成GUI控件的數字貼圖。請看demo。html
咱們能清楚地看到,在角度測量模式下,咱們動態地繪製了兩條邊的長度數字貼圖和角度大小的數字貼圖。對於咱們來講,計算邊長和夾角是很是簡單的工做,但怎麼把結果數字轉變成對應的圖片呢,這裏鯽魚是經過uv座標和數字圖片一一映射實現的。其實原理很是簡單,鯽魚有一張包含0~9和小數點,角度的°的圖片png,用戶輸入是一串包含0~9,小數點和°的字符串,鯽魚將每個字符都綁定圖片的uv座標,這樣構造出的函數輸入是字符串,返回就是對應輸入字符串的uv座標數組。咱們知道構造紋理texture的貼圖就是利用圖片的uv座標來定位圖片在texture上的位置信息,利用這個原理,鯽魚拿回的uv數組就完成了將一個一個數字貼到一片顯式數字的矩形模型中,用戶看到的就會是一片顯式一串數字的矩形(固然矩形是透明的,用戶只能看到數字)。web
以上是原理的解釋,咱們先來看一下數字的png圖片長啥樣。數組
這張就是包含數字和小數點和°的png圖片,注意它是正方形的,且尺寸是2的冪次方。這兩點前者是爲了優化webgl的材質渲染,後者是爲了能被webgl的材質所識別。爲了作成正方形,咱們用空白填充。好了,接下來咱們來看看代碼,關於uv貼圖的映射和texture綁定圖片,咱們先來看uv映射。緩存
1 /** 2 * 字庫 3 * */ 4 let TextImage = function(){ 5 this._library = { 6 ZERO_UV:[0, 1, 0, 0.75, 0.25, 1, 0.25, 0.75], 7 ONE_UV:[0, 0.75, 0, 0.5, 0.25, 0.75, 0.25, 0.5], 8 TWO_UV:[0, 0.5, 0, 0.25, 0.25, 0.5, 0.25, 0.25], 9 THREE_UV:[0, 0.25, 0, 0, 0.25, 0.25, 0.25, 0], 10 FOUR_UV:[0.25, 1, 0.25, 0.75, 0.5, 1, 0.5, 0.75], 11 FIVE_UV:[0.25, 0.75, 0.25, 0.5, 0.5, 0.75, 0.5, 0.5], 12 SIX_UV:[0.25, 0.5, 0.25, 0.25, 0.5, 0.5, 0.5, 0.25], 13 SEVEN_UV:[0.25, 0.25, 0.25, 0, 0.5, 0.25, 0.5, 0], 14 EIGHT_UV:[0.5, 1, 0.5, 0.75, 0.75, 1, 0.75, 0.75], 15 NINE_UV:[0.5, 0.75, 0.5, 0.5, 0.75, 0.75, 0.75, 0.5], 16 DOT_UV:[0.5, 0.5, 0.5, 0.25, 0.75, 0.5, 0.75, 0.25], 17 DEGREE_UV:[0.5, 0.25, 0.5, 0, 0.75, 0.25, 0.75, 0] 18 }; 19 }; 20 21 TextImage.prototype.constructor = TextImage; 22 TextImage.prototype = { 23 24 /** 25 * 經過輸入文字返回圖片,小數點後保留3位 26 * text:輸入的文字 27 * */ 28 getImagesByText:function(text){ 29 text = this.changeUnit(0.001, text); 30 text = this.keepEffectNum(3, text); 31 text = text.toString(); 32 //逐字符匹配圖片 33 let imgUVs = []; 34 for(let i=0; i<text.length; i++){ 35 let imgUV = this.match(text[i]); 36 imgUVs = imgUVs.concat(imgUV); 37 } 38 return imgUVs; 39 }, 40 41 /** 42 * 經過輸入角度返回圖片,小數點後保留3位 43 * angle:輸入的文字 44 * */ 45 getAngleImagesByText:function(angle){ 46 angle = this.keepEffectNum(3, angle); 47 angle = angle.toString(); 48 angle = angle + "#"; 49 //逐字符匹配圖片 50 let imgUVs = []; 51 for(let i=0; i<angle.length; i++){ 52 let imgUV = this.match(angle[i]); 53 imgUVs = imgUVs.concat(imgUV); 54 } 55 return imgUVs; 56 }, 57 58 /** 59 * 單位換算 60 * ratio:換算率 61 * text:輸入的值 62 * */ 63 changeUnit:function(ratio, text){ 64 return ratio * text; 65 }, 66 67 /** 68 * 小數點後保存n位 69 * effect:有效數字 70 * text:原始數字 71 * */ 72 keepEffectNum:function(effect, text){ 73 return text.toFixed(effect); 74 }, 75 76 /** 77 * 匹配字符和圖片 78 * char:字符 79 * */ 80 match:function(char){ 81 let imgUV = undefined; 82 if(char === "0"){ 83 imgUV = this._library.ZERO_UV; 84 }else if(char === "1"){ 85 imgUV = this._library.ONE_UV; 86 }else if(char === "2"){ 87 imgUV = this._library.TWO_UV; 88 }else if(char === "3"){ 89 imgUV = this._library.THREE_UV; 90 }else if(char === "4"){ 91 imgUV = this._library.FOUR_UV; 92 }else if(char === "5"){ 93 imgUV = this._library.FIVE_UV; 94 }else if(char === "6"){ 95 imgUV = this._library.SIX_UV; 96 }else if(char === "7"){ 97 imgUV = this._library.SEVEN_UV; 98 }else if(char === "8"){ 99 imgUV = this._library.EIGHT_UV; 100 }else if(char === "9"){ 101 imgUV = this._library.NINE_UV; 102 }else if(char === "."){ 103 imgUV = this._library.DOT_UV; 104 }else if(char === "#"){ 105 imgUV = this._library.DEGREE_UV; 106 } 107 return imgUV; 108 } 109 }; 110 111 module.exports = TextImage;
咱們看到這個TextImage類擁有一個this._library字庫,其中每個數字都綁定了一串uv座標,即圖片中每個數字的左上角->左下角->右下角->右上角逆時針繞向的4組座標值。在match函數中經過函數輸入參數的字符來返回對應的uv座標數組。這就是數字綁定uv的原理。再來看咱們拿到uv數組怎麼綁定到材質對象中去。請看下面代碼。函數
1 /** 2 * 建立幾何 3 * viewer:視圖對像 4 * textNode:文字節點 5 * width:寬 6 * height:高 7 * position:位置座標 8 * imgUVs:圖片uv數組 9 * texture:數字紋理 10 * */ 11 addGeometry:function(viewer, textNode, width, height, position, imgUVs, texture){ 12 //頂點緩存 13 let w = width; 14 let h = height; 15 //縮放比 16 let scaleRatio = 1; 17 scaleRatio = this.againstScale(position, viewer); 18 w = w*scaleRatio; 19 h = h*scaleRatio; 20 //頂點數組 21 let vertices = []; 22 //首先肯定有幾張圖片 23 let imgNum = imgUVs.length/8; 24 if(imgNum !== 0){ 25 for(let i=0; i<imgNum; i++){ 26 vertices.push(w*i, h, 0, w*i, 0, 0, w*(i+1), h, 0, w*(i+1), 0, 0); 27 } 28 } 29 let array = new Float32Array(vertices); 30 let vertexBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, array, 3); 31 //索引緩存 32 let indices = []; 33 if(imgNum !== 0){ 34 for(let i=0; i<imgNum; i++){ 35 indices.push(4*i, 4*i+1, 4*i+3, 4*i+3, 4*i+2, 4*i); 36 } 37 } 38 let index = new Int8Array(indices); 39 let indexBuffer = new BufferArray(BufferArray.ELEMENT_ARRAY_BUFFER, index, index.length); 40 //繪製圖元 41 let prim = new DrawElements(Primitives.TRIANGLES, indexBuffer); 42 //幾何對象 43 let geom = new Geometry(); 44 geom.setBufferArray('Vertex', vertexBuffer); 45 geom.setPrimitive(prim); 46 //紋理座標 47 let uv = new Float32Array(imgUVs); 48 let uvBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, uv, 2); 49 geom.setBufferArray('Texture', uvBuffer); 50 //將texture加入geometry 51 geom.getStateSet(true).addAttribute(texture, StateAttribute.OVERRIDE); 52 //圖片背景透明 53 let bf = new BlendFunc(BlendFunc.SRC_ALPHA, BlendFunc.ONE_MINUS_SRC_ALPHA); 54 geom.getStateSet(true).addAttribute(bf, StateAttribute.OVERRIDE); 55 //幾何對象加入根節點 56 textNode.addChild(geom); 57 //將textNode的位置平移到position位置 58 let translateMat = Mat4.MemoryPool.alloc(); 59 Mat4.fromTranslation(translateMat, position); 60 Mat4.copy(textNode._matrix, translateMat); 61 //根據主相機視口調整模型旋轉,保證文字老是面向相機 62 this.computeMatrix4MainCamera(textNode._matrix, viewer); 63 //析構 64 Mat4.MemoryPool.free(translateMat); 65 },
咱們看到,咱們的uv轉成BufferArray後被geometry對象所接收,let uv = new Float32Array(imgUVs); let uvBuffer = new BufferArray(BufferArray.ARRAY_BUFFER, uv, 2); geom.setBufferArray('Texture', uvBuffer);經過這三行代碼,咱們的幾何體對象裏就包含了材質信息,鯽魚接下來很歡快地發現,數字貼圖完整地繪製到模型節點中去了。
以上就是對數字GUI組建的完整說明,謝謝同窗們的關注與支持,鯽魚和你們一塊兒進步,鯽魚和同窗們下週再見。post
本文系原創,如需引用,請註明出處:http://www.javashuo.com/article/p-ahxlazhh-ht.html優化