• 技术文章 >web前端 >H5教程

    用HTML5画一个3D的三角形网格

    2016-05-17 09:08:30原创1205
    本教程的主题是利用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 < 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


    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:基于HTML5 的人脸识别技术 下一篇:HTML5本地存储之Web Storage篇
    PHP编程就业班

    相关文章推荐

    • 深入解析asp.net中mvc4自定义404页面(分享)• html5离线存储有哪些• 在今天,利用 HTML5 开发和发布大型跨平台网游,可行性如何?要解决哪些问题?• 避免常见的六种HTML5错误用法 (5-6)• phonegap使用方法介绍(八)操作数据库

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网