美文网首页W3C
3DSDK-NURB曲线曲面

3DSDK-NURB曲线曲面

作者: Cesium4Unreal | 来源:发表于2017-03-17 22:39 被阅读79次

    导语

    非均匀有理B样条,通常简称为NURBS(Non-Uniform Rational B-Splines),实际上已经成为利用计算机处理集合信息时用于形状的表示、设计和数据交换的工业标准。许多国内和国际标准,如IGES,STEP和PHIGS都把NURBS作为集合设计的一个强有力的工具。NURBS取得的巨大成功主要由于以下事实:

    1. NURBS为解析曲线曲面(如圆锥截线和二次曲面)和自由型曲线曲面(如汽车车身和船体外形)的表示提供一种统一的数学方法;
    1. 利用NURBS进行设计非常直观,几乎每个工具和算法都有一个易于理解的几何解释;
    2. NURBS的算法执行速度很快,并且数值稳定;
    3. NURBS曲线曲面在通常的几何变换(如平移、旋转、平行和透视投影)下是不变的;
    4. NURBS是非有理B样条、有理以及非有理Bezier曲线曲面的推广;

    对于大部分人来说,B样条、有理B样条和NURBS有点神秘,有人成NURBS为无人能理解的有理B样条曲线(NoBody Understand Relation B-Splines);研究NURBS的当前首要目的在于呈现三维数据场的可视化,可参考书籍《三维数据场可视化》;

    先睹为快

    番茄天空盒 温度云图 磁场 圆角立方体

    若有所思

    技术无极限,技术是研究不完的,将现有的技术应用的实际的场景中,也验证了技术的能力,又促进了技术推进的动力;那么如上效果,在实际应用中,哪里可能会使用到呢?

    图形学的应用方向 科学可视化应用方向

    实验天地

    上述效果图是基于twaver的3D引擎开发的,自然不能暴露太多的代码;对底层实现比较感兴趣的可以研究three.js的NURB曲线;

    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/Hemisphere.html
    [4].B 样条曲线、样条曲面 NURBS
    [5].http://www.mathcurve.com/
    [6].http://verbnurbs.com/
    [7].https://threejs.org/examples/#webgl_geometry_nurbs
    [8].BURBS Book 书籍 http://vdisk.weibo.com/s/yYC8u8dQ__4m9?from=page_100505_profile&wvr=6&sudaref=www.baidu.com
    http://blog.csdn.net/hunter_wwq/article/details/38707975

    相关文章

      网友评论

      本文标题:3DSDK-NURB曲线曲面

      本文链接:https://www.haomeiwen.com/subject/xcpynttx.html