美文网首页W3C
TWaver3D直线、曲线、曲面的绘制

TWaver3D直线、曲线、曲面的绘制

作者: Cesium4Unreal | 来源:发表于2017-08-05 10:25 被阅读64次

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

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

相关文章

  • TWaver3D直线、曲线、曲面的绘制

    1. WebGL原生线 WebGL支持绘制点、线、三角;绘制线的方法比较简单,给定顶点,设置绘制方式即可; 假设给...

  • Quartz2D绘图

    标签: 裁剪、多边形、绘制图片、绘制文字、截图、曲线、扇形、椭圆、直线 绘图基本格式 一、绘制直线(虚线为多条直线...

  • 上下文绘图,滤镜简单使用

    一、drawRect绘制功能 1.绘制直线 精简绘制直线 2. 绘制椭圆 3. 绘制弧形 4. 绘制贝塞尔曲线 5...

  • Android自定义控件(三 .1)Path贝塞尔曲线

    前一篇文章讲了Path绘制直线以及各种基本图形,这篇文主要说Path绘制曲线,就是曲线中非常有名的贝赛尔曲线。贝赛...

  • iOS:贝塞尔曲线(UIBezierPath)-----OC

    贝塞尔曲线是一个画图的类,需在drawRect方法中绘制;可以绘制直线、矩形、圆、椭圆以及其他复杂的图形贝塞尔曲线...

  • iOS:贝塞尔曲线(UIBezierPath)-----Swif

    贝塞尔曲线是一个画图的类,需在drawRect方法中绘制;可以绘制直线、矩形、圆、椭圆以及其他复杂的图形贝塞尔曲线...

  • Egret矢量绘图与遮罩

    绘制矢量图形 Egret中封装了Graphics类实现矢量绘图功能,可以绘制矩形、圆形、直线、曲线、弧线等。Gra...

  • Android Path详解

    Path 路径,可用于绘制直线、曲线构成几何路径,还可以用于根据路径绘制文字。 常用api 移动、连线、闭合、添加...

  • 2019三年级下册美术作业

    3匀称 2曲线与直线 1对称与规律

  • Path、PathMeasure详解

    1、概念 路径,可用于绘制直线,曲线构成几何路径,还可用于根据路径绘制文字 2、常用API 常用API如移动,连线...

网友评论

    本文标题:TWaver3D直线、曲线、曲面的绘制

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