TWaver3D直線、曲線、曲面的繪制


插播一則廣告(長期有效)

TWaver需要在武漢JavaScript工程師若干 
要求:對前端技術(JavasScript、HTML、CSS),對可視化技術(Canvas、WebGL)有濃厚的興趣 
基礎不好的可培養,基礎好的可共謀大事 
感興趣的給我發郵件:hr@servasoft.com

————————————————————正文的分割線—————————————————————-

今天來說關於繪圖的那些事兒。

先說說繪圖引擎的種類。目前市面上繪圖引擎大致可以分為兩類。一類基於HTML技術,比如TWaver2D/3D引擎。HTML5是業界公認的Web標准和最熱門和主流的技術,可以在瀏覽器中直接創建2D、3D場景,無需安裝任何插件,幾乎已經應用到所有行業的Web應用中。目前所有的主流瀏覽器都很好的支持html5技術,包括手機、平板等移動端瀏覽器的支持。 
這里寫圖片描述

還有一種是Unity公司的Unity3D引擎。unity3d需要在瀏覽器中安裝專門的播放器插件才能運行,有點類似正在垂死掙扎的Flash技術。另外,Unity3D主要支持桌面瀏覽器,並不支持移動端的瀏覽器插件。由於安裝插件不便利,並且有一定的安全隱患,所以Unity3D在企業應用中並不常見,反倒在游戲行業中能夠很好地一展身手。 
這里寫圖片描述


下面就分享一下如何用 TWaver3D引擎繪圖吧。

1. WebGL原生線

WebGL支持繪制點、線、三角;繪制線的方法比較簡單,給定頂點,設置繪制方式即可;

image.png

image.png

假設給定頂點信息為:

var vertices = new Float32Array([
0.0, 0.5, -0.5, -0.5, 0.25, -0.5
]);

  

調用gl.drawArrays(gl.LINE_STRIP, 0, 3);后效果如下:

Chrome: 
image.png

Safari: 
image.png

另外還有個兼容性問題,在Windows上,繪制線的時候無法指定線寬。OpenGL本身有glLineWidth這個方法,而且在WebGL中也有這個方法。但是在Windows雖然調用不會失敗,但是也不會生效,無論是在Chrome還是在FireFox上測試都無效。但是Linux上有效,應該是操作系統的限制問題。這個問題之前就有人提出過,如果有興趣可以看看https://bugs.chromium.org/p/chromium/issues/detail?id=60124。也許在以后的WebGL版本中會修復這個問題吧。測試網站http://alteredqualia.com/tmp/webgl-linewidth-test/。 
設置lineWidth為10后,Chrome效果不變,Safari線條加粗了. 
image.png

測試網站測試:

Chrome不正常 
image.png

Safari正常 
image.png

FireFox正常: 
image.png

是Chrome長期存在的一個Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=60124

image.png 
可以參考WebGL大咖彪叔的文章:WebGL 繪制Line的bug

2. mono.Line類

構造函數: 
image.png

實線:

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);

  

image.png

虛線: 
原來的參數是通過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]);

  

image.png

改變pattern后的效果:實線長一點,虛線短些; 
image.png

創建矩形:

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);

 

image.png

創建橢圓,並分段設置顏色

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);

  

image.png

image.png

//創建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);

 

  • image.png
//創建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);

  

image.png

3. mono.LineX類

正如上文所說,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');

  

image.png

4. mono.PathNode、mono.PathLine、mono.PathCube

路徑體(mono.PathNode)這是一種復雜的形狀體,由兩個任意形狀進行控制:切面形狀,以及前進走向。最終形狀是該切面形狀沿着前進走向進行移動而形成的物體。例如,一個圓形切面沿着一個多邊形移動,就會形成一個復雜的管線物體。這種形狀還可以控制兩個端頭是否封閉、封閉的形狀和尺寸,橫切方向是否閉合、閉合角度、閉合樣式等。通過控制這些參數,可以創建例如管線、彎管、香腸體、切開的管線等。

image.png

image.png 
詳細參考TWaver官方文檔,本文不再累述。

http://doc.servasoft.com/twaver-document-center/recommended/twaver-html5-3d-v2/using-elements/elements/#monoPathNode

5. mono.NurbsCurve類

image.png

權威書籍:《非均勻有理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);

  

image.png

在實際應用中,我們會根據曲線的高度值,設置不同的顏色,來模擬溫度場之類的效果。

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'),
});

  

 

image.png

再制作一個彈簧效果 
image.png

這只是用一些數學公式模擬出來的效果,如若使用比較真實的數據,看看效果如何: 
image.png

大黃兔正臉照 
image.png

側臉照 
image.png

一句話,逼真!

5. mono.NurbsSurface

/**
* 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);

  

image.png

將一幅2D溫度雲圖轉換為3D效果: 
image.png

image.png

結合數學知識,可以展現各種各樣的效果: 
番茄天空盒(內嵌溫度場) 
image.png

圖像RGB展示 
image.png

引力場 
image.png

關於繪圖就說到這,TWaver的3D引擎還是挺強大的,個人覺得呈現效果也比較美麗。到目前為止,我遇到的大大小小上百個case,都能用它得到解決。

有興趣的可以戳網址http://servasoft.com/download.html下載TWaver3D引擎開發包,自己上手玩一把。

6.參考鏈接:

1.http://codeazur.com.br/experiments/webgl_curve_1/ 
2.https://mattdesl.svbtle.com/drawing-lines-is-hard 
[3].https://www.khronos.org/webgl/wiki/Demo_Repository 
[4].http://nurbscalculator.in/ 
[5].http://omni360.github.io/webcad/Org/three.js-master/examples/webgl_geometry_ctrnurbs2d.html 
[6].https://www.ibiblio.org/e-notes/Splines/Intro.htm 
[7].https://www.ibiblio.org/e-notes/webgl/models.htm#spline


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM