MONO哥須要在武漢招JavaScript工程師若干
要求:對前端技術(JavasScript、HTML、CSS),對可視化技術(Canvas、WebGL)有濃厚的興趣
基礎很差的可培養,基礎好的可共謀大事
感興趣的給我發郵件:hr@servasoft.comhtml
------------------------------------------------------------正文的分割線----------------------------------------------------------------前端
今天來講關於繪圖的那些事兒。html5
先說說繪圖引擎的種類。目前市面上繪圖引擎大體能夠分爲兩類。一類基於HTML技術,好比TWaver2D/3D引擎。HTML5是業界公認的Web標準和最熱門和主流的技術,能夠在瀏覽器中直接建立2D、3D場景,無需安裝任何插件,幾乎已經應用到全部行業的Web應用中。目前全部的主流瀏覽器都很好的支持HTML5技術,包括手機、平板等移動端瀏覽器的支持。git
還有一種是Unity公司的Unity3D引擎。Unity3D須要在瀏覽器中安裝專門的播放器插件才能運行,有點相似正在垂死掙扎的Flash技術。另外,Unity3D主要支持桌面瀏覽器,並不支持移動端的瀏覽器插件。因爲安裝插件不便利,而且有必定的安全隱患,因此Unity3D在企業應用中並不常見,反倒在遊戲行業中可以很好地一展身手。github
下面就分享一下如何用 TWaver3D引擎繪圖吧。web
WebGL支持繪製點、線、三角;繪製線的方法比較簡單,給定頂點,設置繪製方式便可;算法
假設給定頂點信息爲:瀏覽器
var vertices = new Float32Array([ 0.0, 0.5, -0.5, -0.5, 0.25, -0.5 ]);
調用gl.drawArrays(gl.LINE_STRIP, 0, 3);後效果以下:安全
Chrome:ide
Safari:
另外還有個兼容性問題,在Windows上,繪製線的時候沒法指定線寬。OpenGL自己有glLineWidth這個方法,並且在WebGL中也有這個方法。可是在Windows雖然調用不會失敗,可是也不會生效,不管是在Chrome仍是在FireFox上測試都無效。可是Linux上有效,應該是操做系統的限制問題。這個問題以前就有人提出過,若是有興趣能夠看看https://bugs.chromium.org/p/c...。也許在之後的WebGL版本中會修復這個問題吧。測試網站http://alteredqualia.com/tmp/...。
設置lineWidth爲10後,Chrome效果不變,Safari線條加粗了.
測試網站測試:
Chrome不正常
Safari正常
FireFox正常:
是Chrome長期存在的一個Bug: https://bugs.chromium.org/p/c...
能夠參考WebGL大咖彪叔的文章:WebGL 繪製Line的bug
構造函數:
實線:
var line = new mono.Line({ vertices:[ new mono.Vec3( -100, 0, 0 ), new mono.Vec3( 100, 100, 0 ), ], type:'mono.LinePieces', styles:{ 'm.color':'red', }, }); box.add(line);
虛線
原來的參數是經過segments來計算出更多的頂點信息;其實能夠經過配置line的style屬性,如line.pattern = [10,2]來計算出頂點信息;
封裝了mono.Line.createDottedLine方法,用於根據pattern建立虛線;
var line = new mono.Line({ type:TGL.LinePieces, styles:{ 'm.color':'green', 'm.type': 'phong', 'm.ambient': 'red', } }); line = mono.Line.createDottedLine(line,[ new mono.Vec3( -200, 100, -100 ), new mono.Vec3( 160, 100, 0 ), new mono.Vec3( 300, -100, 100 ), new mono.Vec3( -300, -100, 200 ), new mono.Vec3( -200, 100, 0 ), new mono.Vec3( -200, 100, -100 ), ],[6,12]);
改變pattern後的效果:實線長一點,虛線短些;
建立矩形:
mono.Line.createRectangle = function(width, height, segments) { // width:寬度, height:高度, segments:分片數 var line = mono.Line.createRectangle(200,200,10); line.setType(TGL.LineStrip); line.setPositionY(-30); line.setPositionX(20); line.setStyle('m.color','red'); box.add(line);
建立橢圓,並分段設置顏色
var line = mono.Line.createEllipse(120,80,100,Math.PI * 2,0,true); line.setPositionY(0); line.setPositionX(0); line.setMaterialStyle('vertexColors',true); line.setMaterialStyle('linewidth',10); line.setMaterialStyle('linejoin','miter'); line.setType(TGL.LinePieces); var vertices = line.getVertices(); var colors = [], color; for(var i = 0;i<vertices.length;i++){ var vertex = vertices[i]; if(vertex.x > 0 && vertex.y > 0){ color = new mono.Color('red'); }else if(vertex.x > 0 && vertex.y < 0){ color = new mono.Color('green'); }else if(vertex.x < 0 && vertex.y < 0){ color = new mono.Color('orange'); }else{ color = new mono.Color('yellow'); } colors.push(color); } line.setColors(colors); box.add(line);
//建立Helix螺旋狀線條 //mono.Line.createHelix = function(line,startRadius, endRadius, height, turns, segments) // startRadius:起始半徑, endRadius:結束半徑, height:高度, turns:轉數, segments:分片數 var line = mono.Line.createHelix(-100,250,200,10,400); line.setPositionY(30); line.setPositionX(20); line.setMaterialStyle('linewidth',10); line.setStyle('m.color','red'); box.add(line);
//建立Ellipse橢圓線條 // mono.Line.createEllipse(xRadius, yRadius, segments, aStartAngle, aEndAngle, aClockwise) // xRadius,yRadius:橢圓的半徑,segments:分片數量,aStartAngle:起始角度,aEndAngle:結束角度,aClockwise:是否逆時針 var line = mono.Line.createEllipse(120,80,100,0,Math.PI/2,true); // line.setType(TGL.LinePieces); line.setPositionY(30); line.setPositionX(20); line.setStyle('m.color','red'); line.setMaterialStyle('linewidth',10); box.add(line);
正如上文所說,Chrome不支持設置線寬,只能本身模擬;因而建立了mono.LineX;
如圖,藍色的爲LineX效果。可用於繪製管線等效果;
var lineX = new mono.LineX([ {x:-180, y:100,z: -100}, {x:120, y:100, z:0}, {x:280, y:-100, z:100}, {x:-280, y:-100, z:200}, {x:-180, y:100, z:0}, {x:-180, y:100, z:-100}, ], ['red', 'red', 'red', 'red'], 10); lineX.setStyle('m.color','blue');
路徑體(mono.PathNode)這是一種複雜的形狀體,由兩個任意形狀進行控制:切面形狀,以及前進走向。最終形狀是該切面形狀沿着前進走向進行移動而造成的物體。例如,一個圓形切面沿着一個多邊形移動,就會造成一個複雜的管線物體。這種形狀還能夠控制兩個端頭是否封閉、封閉的形狀和尺寸,橫切方向是否閉合、閉合角度、閉合樣式等。經過控制這些參數,能夠建立例如管線、彎管、香腸體、切開的管線等。
詳細參考TWaver官方文檔,本文再也不累述。http://doc.servasoft.com/twav...
權威書籍:《非均勻有理B樣條(第2版)》
非均勻有理B樣條,一般簡稱爲NURBS(Non-Uniform Rational B-Splines),實際上已經成爲利用計算機處理集合信息時用於形狀的表示、設計和數據交換的工業標準。許多國內和國際標準,如IGES,STEP和PHIGS都把NURBS做爲集合設計的一個強有力的工具。NURBS取得的巨大成功主要因爲如下事實[1]:
NURBS爲解析曲線曲面(如圓錐截線和二次曲面)和自由型曲線曲面(如汽車車身和船體外形)的表示提供一種統一的數學方法;
利用NURBS進行設計很是直觀,幾乎每一個工具和算法都有一個易於理解的幾何解釋;
NURBS的算法執行速度很快,而且數值穩定;
NURBS曲線曲面在一般的幾何變換(如平移、旋轉、平行和透視投影)下是不變的;
NURBS是非有理B樣條、有理以及非有理Bezier曲線曲面的推廣;
對於大部分人來講,B樣條、有理B樣條和NURBS有點神祕,有人成NURBS爲無人能理解的有理B樣條曲線(NoBody Understand Relation B-Splines);
研究NURBS的當前首要目的在於呈現三維數據場的可視化,可參考書籍《三維數據場可視化》[2];
NURBS曲線,貌似比較神祕,其實也很是的容易理解;製做模型的曲線必定要逼真,曲線越逼真,模型就會越真實。而通常的直線,曲線是很難達到這樣效果的,因此引入了NURBS曲線。
/** * {[TGL.Line]} line * {[Array of vector(3|4)]]} ctrlPoints 曲線的控制點 * {[Number]} degree 曲線的最高指數 * {[Number]} count 曲線每段須要插入點的個數 * {[Object]} ctrlCond 線條控制條件 */ TGL.Line.createNurbs = function(line, ctrlPoints, degree, count, ctrlCond){}
隨機單色波浪線: var points = [0,-200,500,0,1000,-400,-10,500,-1000,0,0,100,-100,0,0,0,0,0]; var ctrlPoints = []; for ( var i = 0, j = 10; i < j; i ++ ) { ctrlPoints.push( new TGL.Vec3( -500 + 100 * i , points[i], 0)); } var line = mono.Line.createNurbs(ctrlPoints,3, 50, { }); line.s({ 'm.type': 'phong', 'm.color':'green' }); line.setMaterialStyle('linewidth',10); line.setType(TGL.LineStrip); box.add(line);
在實際應用中,咱們會根據曲線的高度值,設置不一樣的顏色,來模擬溫度場之類的效果。
var line = mono.Line.createNurbs(ctrlPoints,3, 50, { skyY : 100, skyColor : new mono.Color('red'), horizonY: 0, horizonColor: new mono.Color('yellow'), earthY : -100, earthColor: new mono.Color('green'), });
再製做一個彈簧效果
這只是用一些數學公式模擬出來的效果,如若使用比較真實的數據,看看效果如何:
大黃兔正臉照
側臉照
一句話,逼真!
/** * NurbsSurface 非均勻有理樣條B樣條曲面 * NURBS是非有理B樣條、有理以及非有理Bezier曲線曲面的推廣 * @class mono.NurbsSurface * @constructor * @extends mono.Curve * @param {Number} [degreeU] U方向階數 <= U點數 - 1 * @param {Number} [degreeV] V方向階數 <= V點數 - 1 * @param {Number} [ctrlPoints] 曲面的控制點 * @return {mono.NurbsSurface} NurbsSurface對象 * @example * */
var ctlPoints = [ [ new mono.Vec4(-200, 0, -200, 1 ), new mono.Vec4(-200, 100, -100, 1 ), new mono.Vec4(-200, -100, 100, 1 ), new mono.Vec4(-200, 0, 200, 1 ), new mono.Vec4(-200, 100, 200, 1 ), new mono.Vec4(-200, 0, 300, 1 ), ], [ new mono.Vec4(0, 0, -200, 1 ), new mono.Vec4(0, 100, -100, 1 ), new mono.Vec4(0, -100, 100, 1 ), new mono.Vec4(0, 0, 200, 1 ), new mono.Vec4(0, 100, 200, 1 ), new mono.Vec4(0, 0, 300, 1 ), ], ]; var degreeU = 0;// 階數 <= 點數 - 1 = 3 -1 var degreeV = 3;//階數 <= 點數 - 1 = 6 - 1 var nurbsSurface = new mono.NurbsSurface(degreeU, degreeV, ctlPoints); var surface = window.surface = new mono.Surface(nurbsSurface, 3,150,{ skyY : 100, horizonY: 0, earthY : -100, skyColor : new mono.Color('red'), horizonColor: new mono.Color('gray'), earthColor: new mono.Color('green'), }); surface.s( { 'm.type': 'basic', 'm.color': 'white', 'm.side':mono.DoubleSide, 'm.ambient': 'white', // 'm.texture.image':'./images/collage.jpg', // 'm.wireframe':true, 'm.wireframeLinewidth': 1, 'm.wireframeLinecolor': 'orange', 'm.wireframeLineopacity': 1, }); surface.setSelectable(false); box.add(surface);
將一幅2D溫度雲圖轉換爲3D效果:
結合數學知識,能夠展示各類各樣的效果:
番茄天空盒(內嵌溫度場)
圖像RGB展現
引力場
關於繪圖就說到這,TWaver的3D引擎仍是挺強大的,我的以爲呈現效果也比較美麗。到目前爲止,我遇到的大大小小上百個case,都能用它獲得解決。
有興趣的能夠戳網址http://servasoft.com/download...下載TWaver3D引擎開發包,本身上手玩一把。
[1].http://codeazur.com.br/experi...
[2].https://mattdesl.svbtle.com/d...
[3].https://www.khronos.org/webgl...
[4].http://nurbscalculator.in/
[5].http://omni360.github.io/webc...
[6].https://www.ibiblio.org/e-not...
[7].https://www.ibiblio.org/e-not...