插播一则广告(长期有效)

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支持绘制点、线、三角;绘制线的方法比较简单,给定顶点,设置绘制方式即可;

假设给定顶点信息为:

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

  

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

Chrome: 

Safari: 

另外还有个兼容性问题,在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线条加粗了. 

测试网站测试:

Chrome不正常 

Safari正常 

FireFox正常: 

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

 
可以参考WebGL大咖彪叔的文章:WebGL 绘制Line的bug

2. mono.Line类

构造函数: 

实线:

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

  

虚线: 
原来的参数是通过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]);

  

改变pattern后的效果:实线长一点,虚线短些; 

创建矩形:

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

 

创建椭圆,并分段设置颜色

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

  

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

  

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

  

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

路径体(mono.PathNode)这是一种复杂的形状体,由两个任意形状进行控制:切面形状,以及前进走向。最终形状是该切面形状沿着前进走向进行移动而形成的物体。例如,一个圆形切面沿着一个多边形移动,就会形成一个复杂的管线物体。这种形状还可以控制两个端头是否封闭、封闭的形状和尺寸,横切方向是否闭合、闭合角度、闭合样式等。通过控制这些参数,可以创建例如管线、弯管、香肠体、切开的管线等。

 
详细参考TWaver官方文档,本文不再累述。

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

5. mono.NurbsCurve类

权威书籍:《非均匀有理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);

  

在实际应用中,我们会根据曲线的高度值,设置不同的颜色,来模拟温度场之类的效果。

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

  

再制作一个弹簧效果 

这只是用一些数学公式模拟出来的效果,如若使用比较真实的数据,看看效果如何: 

大黄兔正脸照 

侧脸照 

一句话,逼真!

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

  

将一幅2D温度云图转换为3D效果: 

结合数学知识,可以展现各种各样的效果: 
番茄天空盒(内嵌温度场) 

图像RGB展示 

引力场 

关于绘图就说到这,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

TWaver3D直线、曲线、曲面的绘制的更多相关文章

  1. 7.5.5编程实例-Bezier曲线曲面绘制

    (a)Bezier曲线                         (b) Bezier曲面 1. 绘制Bezier曲线 #include <GL/glut.h> GLfloat ct ...

  2. 用OpenGL进行曲线、曲面的绘制

    实验目的 理解Bezier曲线.曲面绘制的基本原理:理解OpenGL中一维.二维插值求值器的用法. 掌握OpenGL中曲线.曲面绘图的方法,对比不同参数下的绘图效果差异: 代码1:用四个控制点绘制一条 ...

  3. 使用C#三维图形控件进行曲线曲面分析

    使用AnyCAD.Net三维图图形控件能够计算曲线的切线.法线.曲率.长度等,能够计算曲面的uv切线.法线.面积等. 代码示例一:曲线分析 Platform.LineStyle lineStyle = ...

  4. 《MATLAB从入门到放弃》二维曲线和图形绘制基础(二):使用Help文档学习line、plot、plotyy、subplot、hold绘图函数

    目录: »  plot 最常用的二维曲线绘图函数 >  帮助文档 >  基本使用语法 >  线条的样式.符号和颜色调整 >  图形属性调整 >  使用图形句柄进行设置 » ...

  5. 算法+OpenCV】基于opencv的直线和曲线拟合与绘制(最小二乘法)

    http://blog.csdn.net/guduruyu/article/details/72866144 最小二乘法多项式曲线拟合,是常见的曲线拟合方法,有着广泛的应用,这里在借鉴最小二乘多项式曲 ...

  6. 《MATLAB从入门到放弃》二维曲线和图形绘制基础(一): 什么是图形对象和句柄 ?

    图形对象 一个图形包含了不同的对象 图形包括 核心对象和绘制对象 .  核心对象 线条对象 : line 文本对象 : text 矩形对象 : rectangle 补丁对象 : patch 图像对象  ...

  7. 将caffe训练时loss的变化曲线用matlab绘制出来

    1. 首先是提取 训练日志文件; 2. 然后是matlab代码: clear all; close all; clc; log_file = '/home/wangxiao/Downloads/43_ ...

  8. numpy.meshgrid的理解以及3D曲面图绘制(梯度下降法实现过程)

    相关概念: 1.x向量和y向量 import numpy as np import matplotlib.pyplot as plt x = np.array([[0,1,2,3], [0,0,0,0 ...

  9. canvas绘制贝塞尔曲线

    原文:canvas绘制贝塞尔曲线 1.绘制二次方贝塞尔曲线 quadraticCurveTo(cp1x,cp1y,x,y); 其中参数cp1x和cp1y是控制点的坐标,x和y是终点坐标 数学公式表示如 ...

随机推荐

  1. C++语言中的static关键字的作用是什么?

    在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变.在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问.它是一个本地的全局变量.在模块 ...

  2. 北京师范大学第十四届ACM决赛-重现赛 F:Training Plan(DP)

    传送门 题意 将n个数分成m个集合,\(V_i表示max(x-y),x,y∈第\)i个集合,\(求minΣV_i\) 分析 我们先对难度排序,令dp[i][j]表示前i个数分成j个集合的最小费用 转移 ...

  3. Mantis优化改造(技术篇)

    为什么要写这篇? 既然都过去这么久了,都回忆不起来了,为什么还要整理出来这篇文章呢? 这还要追溯到2018年3月份. 当时换工作,面试了国内某知名电视厂商. 简历上面写了我优化改造了bug管理系统ma ...

  4. Linux 导出Okular 编辑的pdf批注

    1.环境 ubuntu 14.04 LTS Okular Version 0.19.3 Using KDE Development Platform 4.13.3 2.方法 2.1只导出批注,不改变p ...

  5. vue中的问题思考

    1.为什么 data 要写成函数,而不允许写成对象? 思考:data是 Vue 实例上的一个属性.2. 对象是对于内存地址的引用.3. 函数有自己的作用域空间. 第一点无可厚非,data属性附着于 V ...

  6. LookupError: unknown encoding: idna 的处理方法

    写了一个脚本,想把它打包成exe文件,在python编译器中运行正常,但是打包成.exe文件运行报错 LookupError: unknown encoding: idna 找遍资料终于找到了解决方法 ...

  7. POJ 1692 Crossed Matchings dp[][] 比较有意思的dp

    http://poj.org/problem?id=1692 这题看完题后就觉得我肯定不会的了,但是题解却很好理解.- - ,做题阴影吗 所以我还是需要多思考. 题目是给定两个数组,要求找出最大匹配数 ...

  8. UESTC - 878 温泉旅店 二维费用背包问题

    http://acm.uestc.edu.cn/#/problem/show/878 设dp[i][j][k]表示在前i个数中,第一个得到的异或值是j,第二个人得到的异或值是k的方案数有多少种. 因为 ...

  9. RHEL 6.5----Nginx负载均衡

    实验环境 主机名 IP master 192.168.30.130 node-1 192.168.30.131 node-2 192.168.30.132 在master上安装 本次安装过程统一采用Y ...

  10. hadoop-0.20.2伪分布式安装简记

    1.准备环境 虚拟机(redhat enterprise linux 6.5) jdk-8u92-linux-x64.tar.gz hadoop-0.20.2.tar.gz 2.关闭虚拟机的防火墙,s ...