本教程的主题是利用html5技术在2d和3d图形之间搭一座互通的桥梁(通过webgl方式)。今天我将展示如何使用一个多边形网格绘制一个三维对象。一个多边形网格或非结构化网格是一个集合的顶点,边缘和面孔,在3 d电脑图像和实体建模定义了一个多面体的对象的形状。通常由三角形的面孔,四边形或其他简单凸多边形,因为这样可以简化渲染,但也可能是由更一般的凹多边形,或多边形的洞。
为了演示,我们准备了简单的三维物体——一个多维数据集和多维领域
html code
通常我们会在canvas里做一个简单的标记
triangle mesh for 3d objects in html5 | script tutorials
please use up / down keys to change opacity
我提取一个生成的对象初始化来:
这意味着如果我们需要显示一个多维数据集——你必须取消第一个一行,如果你想显示一个球体与6张面孔——选择第二个变体。
js code
js的代码分为三部分:主体的代码,网格代码和转换代码
meshes.js
// get random color
function getrandomcolor() {
var letters = '0123456789abcdef'.split('');
var color = '#';
for (var i = 0; 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.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.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.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 for (var i = 0; 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 for (var i = 0; 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 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 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 0) && (y 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.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 var max = obj.distances[obj.faces[i][0]];
for (var f = 1; 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 aprjpoints[i] = project(distance, obj.points[i], ihalfx, ihalfy);
}
// draw an object (surfaces)
for (var i = 0; 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 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