非均勻有理B樣條,一般簡稱爲NURBS(Non-Uniform Rational B-Splines),實際上已經成爲利用計算機處理集合信息時用於形狀的表示、設計和數據交換的工業標準。許多國內和國際標準,如IGES,STEP和PHIGS都把NURBS做爲集合設計的一個強有力的工具。NURBS取得的巨大成功主要因爲如下事實:javascript
NURBS爲解析曲線曲面(如圓錐截線和二次曲面)和自由型曲線曲面(如汽車車身和船體外形)的表示提供一種統一的數學方法;html
利用NURBS進行設計很是直觀,幾乎每一個工具和算法都有一個易於理解的幾何解釋;java
NURBS的算法執行速度很快,而且數值穩定;web
NURBS曲線曲面在一般的幾何變換(如平移、旋轉、平行和透視投影)下是不變的;算法
NURBS是非有理B樣條、有理以及非有理Bezier曲線曲面的推廣;canvas
對於大部分人來講,B樣條、有理B樣條和NURBS有點神祕,有人成NURBS爲無人能理解的有理B樣條曲線(NoBody Understand Relation B-Splines);研究NURBS的當前首要目的在於呈現三維數據場的可視化,可參考書籍《三維數據場可視化》;ide
技術無極限,技術是研究不完的,將現有的技術應用的實際的場景中,也驗證了技術的能力,又促進了技術推動的動力;那麼如上效果,在實際應用中,哪裏可能會使用到呢?工具
上述效果圖是基於twaver的3D引擎開發的,天然不能暴露太多的代碼;對底層實現比較感興趣的能夠研究three.js的NURB曲線;webgl
/** * {[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 ctrlPoints = []; var a = 300; var n = 10; var offset = 2 * Math.PI / 100 /n ; var b = 100; for(var t= 0;t<= 2*Math.PI;t+= offset){ var x = -b * b /a * Math.cos(n * t); var y = - 1 * b * b / a * Math.sin(n * t); var z = b * t; ctrlPoints.push(new TGL.Vec3(x,z,y)); } var line = mono.Line.createNurbs(ctrlPoints, 1, 1,{ skyY : 500, skyColor : new mono.Color('orange'), horizonY: 0, horizonColor: new mono.Color('orange'), earthY : -100, earthColor: new mono.Color('orange'), }); line.s({ 'm.type': 'phong', }); box.add(line);
/** * 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 * */
<!DOCTYPE html> <html> <head> <title>Mono Test</title> <script type="text/javascript" src = "../src/t.js"></script> <script type="text/javascript"> function init(){ var box = new mono.DataBox(); var network= new mono.Network3D(box, null, monoCanvas); mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight'); network.setClearColor('#CDCDCD'); box.add(new mono.AmbientLight(0x888888)); 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': 'orange', 'm.side':mono.DoubleSide, 'm.ambient': 'orange', 'm.texture.image':'./images/collage.jpg', 'm.wireframe':true, 'm.wireframeLinewidth': 1, 'm.wireframeLinecolor': 'orange', 'm.wireframeLineopacity': 1, }); surface.setSelectable(false); box.add(surface); } </script> </head> <body 'init()'> <div> <canvas id="monoCanvas"/> </div> </body> </html>
<!DOCTYPE html> <html> <head> <title>Mono Test</title> <script type="text/javascript" src = "../src/t.js"></script> <script type="text/javascript"> function init(){ var box = new mono.DataBox(); var network= new mono.Network3D(box, null, monoCanvas); mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight'); network.setClearColor('#CDCDCD'); // network.setShowAxis(true); box.add(new mono.AmbientLight(0x888888)); var myImage = new Image(); myImage.src = "./images/hot.png"; myImage. function(){ var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); ctx.drawImage(myImage,0,0); var imgData = ctx.getImageData(0,0,canvas.width,canvas.height); var ctlPoints = []; for(var i = 0; i < imgData.height; ++i){ var vpoints = [] ; for(var j = 0; j < imgData.width; ++j){ var x = i*4*imgData.width + 4*j, r = imgData.data[x], g = imgData.data[x+1], b = imgData.data[x+2], a = imgData.data[x+3]; vpoints.push(new mono.Vec4((j-imgData.width/2)*50,20 * ((r+g+b)/3 - 250/2),(i - imgData.height/2)*50,1)); } ctlPoints.push(vpoints); } // var degreeU = imgData.height - 1;// 階數 <= 點數 - 1 = 3 -1 // var degreeV = imgData.width - 1;//階數 <= 點數 - 1 = 6 - 1 var degreeU = 3; var degreeV = 4; var nurbsSurface = new mono.NurbsSurface(degreeU, degreeV, ctlPoints); var surface = window.surface = new mono.Surface(nurbsSurface, 200,200,{ skyY : 2000, horizonY: 1000, earthY : 500, skyColor : new mono.Color('red'), horizonColor: new mono.Color('yellow'), earthColor: new mono.Color('green'), }); surface.s( { 'm.type': 'basic', 'm.color': 'white', // 'm.side':mono.DoubleSide, 'm.ambient': 'white', 'm.wireframe':true, 'm.wireframeLinewidth': 0.1, 'm.wireframeLinecolor': 'orange', 'm.wireframeLineopacity': 1, // 'm.texture.image':'./images/hot.png', }); surface.setSelectable(false); box.add(surface); } } </script> </head> <body 'init()'> <div> <canvas id="monoCanvas"/> </div> </body> </html>
<!DOCTYPE html> <html> <head> <title>Mono Test</title> <script type="text/javascript" src = "../src/t.js"></script> <script type="text/javascript"> function init(){ var box = new mono.DataBox(); var network= new mono.Network3D(box, null, monoCanvas); network.setClearColor('black'); network.setClearAlpha(1); // network.setBackgroundImage('sky.jpg'); mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight'); var pointLight = new mono.PointLight(0xFFFFFF,1.5); pointLight.setPosition(1000,1000,1000); box.add(pointLight); box.add(new mono.AmbientLight(0x888888)); var camera=network.getCamera(); camera.setPosition(200, 200, 500); var cube = new mono.Sphere(50, 30, 30, 0, Math.PI*2, 0, Math.PI); cube.setPosition(0,40,0); cube.s({ 'm.type': 'phong', 'm.color': 'white', 'm.texture.image':'world1.jpg' }); cube.setSelectable(false); box.add(cube); var ctrlPoints = []; var n = 100; var offset = 2 * Math.PI/n ; var points = []; var a = 400; for(var t= 0;t<= 2*Math.PI;t+= offset){ var x = a*Math.cos(t); var y = 0; // var y = a * Math.sin(t); var z = a*Math.sin(t); points.push(new mono.Vec4(x,y,z,100)); } ctrlPoints.push(points); a= 200; var points = []; for(var t= 0;t<= 2*Math.PI;t+= offset){ var x = a*Math.cos(t); var y = 40; // var y = a * Math.sin(t); var z = a*Math.sin(t); points.push(new mono.Vec4(x,y,z,200)); } ctrlPoints.push(points); a= 5; var points = []; for(var t= 0;t<= 2*Math.PI;t+= offset){ var x = a*Math.cos(t); var y = -120; // var y = a * Math.sin(t); var z = a*Math.sin(t); points.push(new mono.Vec4(x,y,z,400)); } ctrlPoints.push(points); a= 0; var points = []; for(var t= 0;t<= 2*Math.PI;t+= offset){ var x = a*Math.cos(t); var y = -110; // var y = a * Math.sin(t); var z = a*Math.sin(t); points.push(new mono.Vec4(x,y,z,400)); } ctrlPoints.push(points); var degree1 = 2; var degree2 = n - 1; var nurbsSurface = new mono.NurbsSurface(degree1, degree2, ctrlPoints); var surface = new mono.Surface(nurbsSurface, 100,60,{ skyY : 40, horizonY: 0, earthY : -100, skyColor : new mono.Color('#80B9B3'), horizonColor: new mono.Color('#A9DCD7'), earthColor: new mono.Color('#8CEBF4'), }); surface.s( { 'm.type': 'phong', 'm.side':mono.DoubleSide, // 'm.texture.image':'UV_Grid_Sm.jpg', 'm.texture.image':'./images/sky.jpg', // 'm.tansparent':true, // 'm.opacity':0.2, // 'm.texture.image':'sky.jpg', 'm.wireframe':true, 'm.wireframeLinewidth': 1, 'm.wireframeLinecolor': '#33726c', 'm.wireframeLineopacity': 0.9, }); box.add(surface); surface.setPosition(0,40,0); surface.setSelectable(false); } </script> </head> <body onload = 'init()'> <div> <canvas id="monoCanvas"/> </div> </body> </html>
[1]. 權威書籍:《非均勻有理B樣條(第2版)》
[2]. 《三維數據場可視化》
[3]. http://mathworld.wolfram.com/...
[4].B 樣條曲線、樣條曲面 NURBS
[5].http://www.mathcurve.com/
[6].http://verbnurbs.com/
[7].https://threejs.org/examples/...
[8].BURBS Book 書籍 http://vdisk.weibo.com/s/yYC8...
http://blog.csdn.net/hunter_w...spa