3DSDK-NURB曲線曲面

導語

非均勻有理B樣條,一般簡稱爲NURBS(Non-Uniform Rational B-Splines),實際上已經成爲利用計算機處理集合信息時用於形狀的表示、設計和數據交換的工業標準。許多國內和國際標準,如IGES,STEP和PHIGS都把NURBS做爲集合設計的一個強有力的工具。NURBS取得的巨大成功主要因爲如下事實:javascript

  1. NURBS爲解析曲線曲面(如圓錐截線和二次曲面)和自由型曲線曲面(如汽車車身和船體外形)的表示提供一種統一的數學方法;html

  1. 利用NURBS進行設計很是直觀,幾乎每一個工具和算法都有一個易於理解的幾何解釋;java

  2. NURBS的算法執行速度很快,而且數值穩定;web

  3. NURBS曲線曲面在一般的幾何變換(如平移、旋轉、平行和透視投影)下是不變的;算法

  4. NURBS是非有理B樣條、有理以及非有理Bezier曲線曲面的推廣;canvas

對於大部分人來講,B樣條、有理B樣條和NURBS有點神祕,有人成NURBS爲無人能理解的有理B樣條曲線(NoBody Understand Relation B-Splines);研究NURBS的當前首要目的在於呈現三維數據場的可視化,可參考書籍《三維數據場可視化》;ide

先睹爲快

圖片描述
番茄天空盒

圖片描述

圓角立方體

如有所思

技術無極限,技術是研究不完的,將現有的技術應用的實際的場景中,也驗證了技術的能力,又促進了技術推動的動力;那麼如上效果,在實際應用中,哪裏可能會使用到呢?工具

圖形學的應用方向

科學可視化應用方向

實驗天地

上述效果圖是基於twaver的3D引擎開發的,天然不能暴露太多的代碼;對底層實現比較感興趣的能夠研究three.js的NURB曲線;webgl

mono.NurbsCurve使用

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

彈簧效果

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
 * 
 */
曲面
<!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

相關文章
相關標籤/搜索