本文固定链接:http://www.verydemo.com/demo_c101_i57317.html
本教程的主题是利用HTML5技术在2D和3D图形之间搭一座互通的桥梁(通过WebGL方式)。今天我将展示如何使用一个多边形网格绘制一个三维对象。 一个多边形网格或非结构化网格是一个集合的顶点,边缘和面孔,在3 d电脑图像和实体建模定义了一个多面体的对象的形状。通常由三角形的面孔,四边形或其他简单凸多边形,因为这样可以简化渲染,但也可能是由更一般的凹多边 形,或多边形的洞。
为了演示,我们准备了简单的三维物体——一个多维数据集和多维领域
HTML CODE
通常我们会在canvas里做一个简单的标记
<html lang="en" >
<head>
<meta charset="utf-8" />
<meta name="author" content="Script Tutorials" />
<title>Triangle mesh for 3D objects in HTML5 | Script Tutorials</title>
<!-- add styles -->
<link href="css/main.css" rel="stylesheet" type="text/css" />
<!-- add script -->
<script src="js/meshes.js"></script>
<script src="js/transform.js"></script>
<script>
//var obj = new cube();
//var obj = new sphere(6);
var obj = new sphere(16);
</script>
<script src="js/main.js"></script>
</head>
<body>
<div class="container">
<canvas id="scene" height="500" width="700" tabindex="1"></canvas>
<div class="hint">Please use Up / Down keys to change opacity</div>
</div>
</body>
</html>
我提取一个生成的对象初始化来:
<script>
//var obj = new cube();
//var obj = new sphere(6);
var obj = new sphere(16);
</script>
这意味着如果我们需要显示一个多维数据集——你必须取消第一个一行,如果你想显示一个球体与6张面孔——选择第二个变体。
JS CODE
JS的代码分为三部分:主体的代码,网格代码和转换代码
meshes.js
// get random color
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
// prepare object
function prepareObject(o) {
o.colors = new Array();
// prepare normals
o.normals = new Array();
for (var i = 0; i < o.faces.length; i++) {
o.normals[i] = [0, 0, 0];
o.colors[i] = getRandomColor();
}
// prepare centers: calculate max positions
o.center = [0, 0, 0];
for (var i = 0; i < o.points.length; i++) {
o.center[0] += o.points[i][0];
o.center[1] += o.points[i][1];
o.center[2] += o.points[i][2];
}
// prepare distances
o.distances = new Array();
for (var i = 1; i < o.points.length; i++) {
o.distances[i] = 0;
}
// calculate average center positions
o.points_number = o.points.length;
o.center[0] = o.center[0] / (o.points_number - 1);
o.center[1] = o.center[1] / (o.points_number - 1);
o.center[2] = o.center[2] / (o.points_number - 1);
o.faces_number = o.faces.length;
o.axis_x = [1, 0, 0];
o.axis_y = [0, 1, 0];
o.axis_z = [0, 0, 1];
}
// Cube object
function cube() {
// prepare points and faces for cube
this.points=[
[0,0,0],
[100,0,0],
[100,100,0],
[0,100,0],
[0,0,100],
[100,0,100],
[100,100,100],
[0,100,100],
[50,50,100],
[50,50,0],
];
this.faces=[
[0,4,5],
[0,5,1],
[1,5,6],
[1,6,2],
[2,6,7],
[2,7,3],
[3,7,4],
[3,4,0],
[8,5,4],
[8,6,5],
[8,7,6],
[8,4,7],
[9,5,4],
[9,6,5],
[9,7,6],
[9,4,7],
];
prepareObject(this);
}
// Sphere object
function sphere(n) {
var delta_angle = 2 * Math.PI / n;
// prepare vertices (points) of sphere
var vertices = [];
for (var j = 0; j < n / 2 - 1; j++) {
for (var i = 0; i < n; i++) {
vertices[j * n + i] = [];
vertices[j * n + i][0] = 100 * Math.sin((j + 1) * delta_angle) * Math.cos(i * delta_angle);
vertices[j * n + i][1] = 100 * Math.cos((j + 1) * delta_angle);
vertices[j * n + i][2] = 100 * Math.sin((j + 1) * delta_angle) * Math.sin(i * delta_angle);
}
}
vertices[(n / 2 - 1) * n] = [];
vertices[(n / 2 - 1) * n + 1] = [];
vertices[(n / 2 - 1) * n][0] = 0;
vertices[(n / 2 - 1) * n][1] = 100;
vertices[(n / 2 - 1) * n][2] = 0;
vertices[(n / 2 - 1) * n + 1][0] = 0;
vertices[(n / 2 - 1) * n + 1][1] = -100;
vertices[(n / 2 - 1) * n + 1][2] = 0;
this.points = vertices;
// prepare faces
var faces = [];
for (var j = 0; j < n / 2 - 2; j++) {
for (var i = 0; i < n - 1; i++) {
faces[j * 2 * n + i] = [];
faces[j * 2 * n + i + n] = [];
faces[j * 2 * n + i][0] = j * n + i;
faces[j * 2 * n + i][1] = j * n + i + 1;
faces[j * 2 * n + i][2] = (j + 1) * n + i + 1;
faces[j * 2 * n + i + n][0] = j * n + i;
faces[j * 2 * n + i + n][1] = (j + 1) * n + i + 1;
faces[j * 2 * n + i + n][2] = (j + 1) * n + i;
}
faces[j * 2 * n + n - 1] = [];
faces[2 * n * (j + 1) - 1] = [];
faces[j * 2 * n + n - 1 ][0] = (j + 1) * n - 1;
faces[j * 2 * n + n - 1 ][1] = (j + 1) * n;
faces[j * 2 * n + n - 1 ][2] = j * n;
faces[2 * n * (j + 1) - 1][0] = (j + 1) * n - 1;
faces[2 * n * (j + 1) - 1][1] = j * n + n;
faces[2 * n * (j + 1) - 1][2] = (j + 2) * n - 1;
}
for (var i = 0; i < n - 1; i++) {
faces[n * (n - 4) + i] = [];
faces[n * (n - 3) + i] = [];
faces[n * (n - 4) + i][0] = (n / 2 - 1) * n;
faces[n * (n - 4) + i][1] = i;
faces[n * (n - 4) + i][2] = i + 1;
faces[n * (n - 3) + i][0] = (n / 2 - 1) * n + 1;
faces[n * (n - 3) + i][1] = (n / 2 - 2) * n + i + 1;
faces[n * (n - 3) + i][2] = (n / 2 - 2) * n + i;
}
faces[n * (n - 3) - 1] = [];
faces[n * (n - 2) - 1] = [];
faces[n * (n - 3) - 1][0] = (n / 2 - 1) * n;
faces[n * (n - 3) - 1][1] = n - 1;
faces[n * (n - 3) - 1][2] = 0;
faces[n * (n - 2) - 1][0] = (n / 2 - 1) * n + 1;
faces[n * (n - 2) - 1][1] = (n / 2 - 2) * n;
faces[n * (n - 2) - 1][2] = (n / 2 - 2) * n + n - 1;
this.faces=faces;
prepareObject(this);
}
main.js
// inner variables
var canvas, ctx;
var vAlpha = 0.5;
var vShiftX = vShiftY = 0;
var distance = -700;
var vMouseSens = 0.05;
var iHalfX, iHalfY;
// initialization
function sceneInit() {
// prepare canvas and context objects
canvas = document.getElementById('scene');
ctx = canvas.getContext('2d');
iHalfX = canvas.width / 2;
iHalfY = canvas.height / 2;
// initial scale and translate
scaleObj([3, 3, 3], obj);
translateObj([-obj.center[0], -obj.center[1], -obj.center[2]],obj);
translateObj([0, 0, -1000], obj);
// attach event handlers
document.onkeydown = handleKeydown;
canvas.onmousemove = handleMousemove;
// main scene loop
setInterval(drawScene, 25);
}
// onKeyDown event handler
function handleKeydown(e) {
kCode = ((e.which) || (e.keyCode));
switch (kCode) {
case 38: vAlpha = (vAlpha <= 0.9) ? (vAlpha + 0.1) : vAlpha; break; // Up key
case 40: vAlpha = (vAlpha >= 0.2) ? (vAlpha - 0.1) : vAlpha; break; // Down key
}
}
// onMouseMove event handler
function handleMousemove(e) {
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
if ((x > 0) && (x < canvas.width) && (y > 0) && (y < canvas.height)) {
vShiftY = vMouseSens * (x - iHalfX) / iHalfX;
vShiftX = vMouseSens * (y - iHalfY) / iHalfY;
}
}
// draw main scene function
function drawScene() {
// clear canvas
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// set fill color, stroke color, line width and global alpha
ctx.strokeStyle = 'rgb(0,0,0)';
ctx.lineWidth = 0.5;
ctx.globalAlpha= vAlpha;
// vertical and horizontal rotate
var vP1x = getRotationPar([0, 0, -1000], [1, 0, 0], vShiftX);
var vP2x = getRotationPar([0, 0, 0], [1, 0, 0], vShiftX);
var vP1y = getRotationPar([0, 0, -1000], [0, 1, 0], vShiftY);
var vP2y = getRotationPar([0, 0, 0], [0, 1, 0], vShiftY);
rotateObj(vP1x, vP2x, obj);
rotateObj(vP1y, vP2y, obj);
// recalculate distances
for (var i = 0; i < obj.points_number; i++) {
obj.distances[i] = Math.pow(obj.points[i][0],2) + Math.pow(obj.points[i][1],2) + Math.pow(obj.points[i][2], 2);
}
// prepare array with face triangles (with calculation of max distance for every face)
var iCnt = 0;
var aFaceTriangles = new Array();
for (var i = 0; i < obj.faces_number; i++) {
var max = obj.distances[obj.faces[i][0]];
for (var f = 1; f < obj.faces[i].length; f++) {
if (obj.distances[obj.faces[i][f]] > max)
max = obj.distances[obj.faces[i][f]];
}
aFaceTriangles[iCnt++] = {faceVertex:obj.faces[i], faceColor:obj.colors[i], distance:max};
}
aFaceTriangles.sort(sortByDistance);
// prepare array with projected points
var aPrjPoints = new Array();
for (var i = 0; i < obj.points.length; i++) {
aPrjPoints[i] = project(distance, obj.points[i], iHalfX, iHalfY);
}
// draw an object (surfaces)
for (var i = 0; i < iCnt; i++) {
ctx.fillStyle = aFaceTriangles[i].faceColor;
// begin path
ctx.beginPath();
// face vertex index
var iFaceVertex = aFaceTriangles[i].faceVertex;
// move to initial position
ctx.moveTo(aPrjPoints[iFaceVertex[0]][0], aPrjPoints[iFaceVertex[0]][1]);
// and draw three lines (to build a triangle)
for (var z = 1; z < aFaceTriangles[i].faceVertex.length; z++) {
ctx.lineTo(aPrjPoints[iFaceVertex[z]][0], aPrjPoints[iFaceVertex[z]][1]);
}
// close path, strole and fill a triangle
ctx.closePath();
ctx.stroke();
ctx.fill();
}
}
// sort function
function sortByDistance(x, y) {
return (y.distance - x.distance);
}
// initialization
if (window.attachEvent) {
window.attachEvent('onload', sceneInit);
} else {
if (window.onload) {
var curronload = window.onload;
var newonload = function() {
curronload();
sceneInit();
};
window.onload = newonload;
} else {
window.onload = sceneInit;
}
}
查看演示:http://www.script-tutorials.com/demos/319/index.html
下载:用HTML5画一个3D的三角形网格.zip
相关推荐
MATLAB编写三角形网格有限元程序,验证圣维南原理.
三角形网格剖分程序,可以把任意平面区域剖分成三角形网格
3D三角形网格模型补洞算法源代码,原为linux平台下编译,现已改为Windows环境下;由于使用了C++11新特性,需通过VS2013或更高版本编译。
画一个白色的三角形,详见我的博客
学习有限元网格划分的好资源,可以帮助在校生熟系Fortran编程、有限元网格
有限元网格生成极大程度上影响着计算效率,其中四边形优于三角形
mesh2d是一个很好用的三角形网格划分工具
输入条件:二维凸多边形区域 实际输入:围成此区域的边界点集 输出结果:此区域的三角形网格 实际输出:网格数据 网格要求:1任意三角形的任意边长≤1.0; 2 网格节点数目尽量
高级图形学 四边形网格模型转换为三角形网格模型 c++代码及海豚模型示例 打开release文件夹中Tool.exe导入海豚模型即可
等值线是一种离散数据的图形表示方法,在水利、土木、地质、石油勘探等工程和技术领域内广泛的应用。常规的等值线绘制通常采用网格法,其绘制的步骤一般为:离散数据网 格化;等值点的计算;等值线的追踪;光滑和...
基于三角形网格的等值线算法,根据散点数据,自动生成三角形网格,然后生成等值线
C++语言,在PCL环境下的 三角形网格孔洞修复。主要针对曲面重建之后,模型出现了大量孔洞,需要修复。修复步骤很简单,就是基于最小角的剖分修复。
画三角形画三角形画三角形画三角形画三角形画三角形
HTML5绘制3D三角形花圈动画特效是一款三角形花圈动画,支持鼠标拖到控制旋转方向。
它展示了四边形表面网格生成的整个流程
文献英文全名《Finite Volume Solution of the Two Dimensional Euler Equations on a Regular Triangular Mesh》 ...使用有限体积法 求解欧拉方程 基于非结构网格 基础简单,适于初学 作者: A.Jameson, D.Mavriplis
CFD,三角形流场,网格划分,网格计算,计算流体力学
工程中加入CPP,配置好opencv运行即可。
为了简化数值模拟中三角形网格模型之间的接触问题,设计了在接触面上生成一致性三角形网格的算法,基本步骤为构造网格拓扑关系、搜索重叠网格、完善重叠网格、拷贝网格、修补边界空隙。采用面向配对顶点的搜索方法、...