像查找表一样的水密行进立方体?

时间:2014-10-05 22:14:37

标签: voxel marching-cubes

我正在尝试将标量字段多边形化。网格上的每个点只能有1或0的值。我需要为8个点创建一个包含256个多边形数组的数组,但是,与行进立方体不同,这些多边形的边缘只能位于网格的点上。

1 个答案:

答案 0 :(得分:0)

返回数组的Javascript函数需要gl-matrix.js和vec3.ceil

function () {
        var polyConds = [];

        var b = function () {
            var v = 0;
            for (var i = 0; i < arguments.length; i++) {
                v |= 1 << (arguments[i] - 1);
            }
            return v;
        };

        /* 0 */
        polyConds[b()] = [];

        /* 1 */
        polyConds[b(1)] = [];

        /* 2 */
        polyConds[b(1, 2)] = [];
        polyConds[b(1, 4)] = [];
        polyConds[b(1, 8)] = [];

        /* 3 */
        polyConds[b(1, 2, 3)] = [1, 2, 3];
        polyConds[b(1, 2, 7)] = [1, 2, 7, 1, 7, 2];
        polyConds[b(1, 4, 6)] = [1, 4, 6, 1, 6, 4];

        /* 4 */
        polyConds[b(1, 2, 3, 4)] = [1, 2, 3, 2, 4, 3];
        polyConds[b(1, 2, 7, 8)] = [1, 2, 7, 7, 8, 2, 1, 7, 2, 7, 2, 8];
        polyConds[b(1, 2, 3, 6)] = [1, 6, 3, 2, 3, 6];
        polyConds[b(1, 2, 3, 8)] = [1, 2, 3, 2, 3, 8, 2, 8, 3];
        polyConds[b(1, 4, 6, 7)] = [1, 4, 7, 1, 7, 4, 1, 4, 6, 1, 6, 4];
        polyConds[b(1, 2, 3, 5)] = [2, 3, 5];
        polyConds[b(2, 3, 4, 6)] = [2, 6, 3, 3, 6, 4];

        /* 5 */
        polyConds[b(1, 2, 3, 4, 5)] = [2, 3, 5, 2, 4, 3];
        polyConds[b(1, 3, 4, 5, 6)] = [1, 4, 6, 3, 5, 4, 4, 5, 6];
        polyConds[b(1, 4, 5, 6, 7)] = [1, 6, 7];

        /* 6 */
        polyConds[b(1, 2, 3, 4, 5, 6)] = [3, 5, 4, 4, 5, 6];
        polyConds[b(1, 2, 4, 5, 6, 7)] = [1, 7, 4, 4, 7, 6];
        polyConds[b(2, 3, 4, 5, 6, 7)] = [2, 5, 3, 4, 7, 6];

        /* 7 */
        polyConds[b(1, 2, 3, 4, 5, 6, 7)] = [4, 7, 6];

        /* 8 */
        polyConds[b(1, 2, 3, 4, 5, 6, 7, 8)] = [];

        for (var k in polyConds) {
            var points = [
                [0, 0, 0],
                [1, 0, 0],
                [0, 1, 0],
                [1, 1, 0],
                [0, 0, 1],
                [1, 0, 1],
                [0, 1, 1],
                [1, 1, 1],
            ];

            polyConds[k] = polyConds[k].map(function (v) {return points[v - 1]});
        }

        var rotations = [
            [
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), 0),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), Math.PI),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), Math.PI/2*3),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 1, 0), Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 1, 0), Math.PI/2*3),
            ],
            [
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), 0),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), Math.PI),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), Math.PI/2*3),
            ],
        ];

        var unrotations = [
            [
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), 0),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), -Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), -Math.PI),
                quat.setAxisAngle(quat.create(), vec3.fromValues(1, 0, 0), -Math.PI/2*3),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 1, 0), -Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 1, 0), -Math.PI/2*3),
            ],
            [
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), 0),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), -Math.PI/2),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), -Math.PI),
                quat.setAxisAngle(quat.create(), vec3.fromValues(0, 0, 1), -Math.PI/2*3),
            ],
        ];

        for (var i = 0; i < 256; i++)
        for (var a = 0, al = rotations[0].length; a < al; a++)
        for (var b = 0, bl = rotations[1].length; b < bl; b++) {

            var points = [
                [0, 0, 0],
                [1, 0, 0],
                [0, 1, 0],
                [1, 1, 0],
                [0, 0, 1],
                [1, 0, 1],
                [0, 1, 1],
                [1, 1, 1],
            ];

            var vertices = [];
            for (var j = 0; j < 8; j++) {
                if (i >> j & 1) {
                    vertices.push(points[j]);
                }
            }

            for (var j = 0, jl = vertices.length; j < jl; j++) {
                var v = vertices[j];

                vec3.sub(v, v, vec3.fromValues(0.5, 0.5, 0.5));
                vec3.transformQuat(v, v, rotations[0][a]);
                vec3.transformQuat(v, v, rotations[1][b]);
                vec3.ceil(v, v);
            }


            var bits = 0;
            for (var j = 0, jl = vertices.length; j < jl; j++) {
                bits |= 1 << (vertices[j][0] + vertices[j][1] * 2 + vertices[j][2] * 4);
            }

            if (polyConds[bits]) {
                vertices = JSON.parse(JSON.stringify(polyConds[bits]));

                for (var j = 0, jl = vertices.length; j < jl; j++) {
                    var v = vertices[j];

                    vec3.sub(v, v, vec3.fromValues(0.5, 0.5, 0.5));
                    vec3.transformQuat(v, v, unrotations[1][b]);
                    vec3.transformQuat(v, v, unrotations[0][a]);
                    vec3.ceil(v, v);
                }

                polyConds[i] = vertices;

                a = Infinity; // break to first loop
                b = Infinity;
            }
        }

        return polyConds;
    }