【问题标题】:Groups & THREE.MultiMaterial组和三.MultiMaterial
【发布时间】:2016-08-04 19:32:58
【问题描述】:

作为对一些调试器对象和方法进行原型设计的一部分,我创建了一个简单的立方体,每侧都有不同的颜色。我决定使用绘制组和 THREE.Multimaterial,而不是创建多个网格。不幸的是,它只工作了一半,我不明白为什么。

有效的是前两条边(4 个三角形)。任何其他方面都不起作用。其他边都看不到。我添加了调试代码来绘制(基于索引的)顶点法线、(基于索引、手动计算的)面法线和线框 (THREE.WireframeHelper)。

如果我将第二组的计数增加到 9,则没有任何反应。如果我更改组以在前 8 个顶点内引用不同的开始/计数值,则这些更改将按预期工作。在第 8 个顶点以上做任何事情都没有效果。

我还检查了 drawRange 是否设置为从 0 绘制到无穷大。我还排除了数据中的拼写错误,否则法线和线框将不起作用。还有什么我想念的吗?谢谢!

(我在 r76 中发现了问题。在撰写本文时,下面的代码引用了 r79。)

jsfiddle: http://jsfiddle.net/TheJim01/gumftkm4/

HTML:

<script src="http://threejs.org/build/three.js"></script>
<script src="http://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="host"></div>

<script>
// INITIALIZE
var WIDTH = window.innerWidth,
    HEIGHT = window.innerHeight,
    FOV = 35,
    NEAR = 1,
    FAR = 1000;

var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
document.getElementById('host').appendChild(renderer.domElement);

var stats= new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);


var camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 250;

var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 5.0; // need to speed it up a little

var scene = new THREE.Scene();

var light = new THREE.PointLight(0xffffff, 1, Infinity);
light.position.copy(camera.position);

scene.add(light);

function draw(){
    light.position.copy(camera.position);
    renderer.render(scene, camera);
  stats.update();
}
trackballControl.addEventListener('change', draw);

function navStartHandler(e) {
  renderer.domElement.addEventListener('mousemove', navMoveHandler);
  renderer.domElement.addEventListener('mouseup', navEndHandler);
}
function navMoveHandler(e) {
  trackballControl.update();
}
function navEndHandler(e) {
  renderer.domElement.removeEventListener('mousemove', navMoveHandler);
  renderer.domElement.removeEventListener('mouseup', navEndHandler);
}

renderer.domElement.addEventListener('mousedown', navStartHandler);
renderer.domElement.addEventListener('mousewheel', navMoveHandler);
</script>

CSS:

html *{
    padding: 0;
    margin: 0;
    width: 100%;
    overflow: hidden;
}

#host {
    width: 100%;
    height: 100%;
}

JavaScript:

// New Color Cube
(function () {

    var pos = new Float32Array([
        // front
        -1, 1, 1,
        -1, -1, 1,
        1, 1, 1,
        1, -1, 1,
        // right
        1, 1, 1,
        1, -1, 1,
        1, 1, -1,
        1, -1, -1,
        // back
        1, 1, -1,
        1, -1, -1,
        -1, 1, -1,
        -1, -1, -1,
        // left
        -1, 1, -1,
        -1, -1, -1,
        -1, 1, 1,
        -1, -1, 1,
        // top
        -1, 1, -1,
        -1, 1, 1,
        1, 1, -1,
        1, 1, 1,
        // bottom
        -1, -1, 1,
        -1, -1, -1,
        1, -1, 1,
        1, -1, -1
    ]),
    nor = new Float32Array([
        // front
        0, 0, 1,
        0, 0, 1,
        0, 0, 1,
        0, 0, 1,
        // right
        1, 0, 0,
        1, 0, 0,
        1, 0, 0,
        1, 0, 0,
        // back
        0, 0, -1,
        0, 0, -1,
        0, 0, -1,
        0, 0, -1,
        // left
        -1, 0, 0,
        -1, 0, 0,
        -1, 0, 0,
        -1, 0, 0,
        // top
        0, 1, 0,
        0, 1, 0,
        0, 1, 0,
        0, 1, 0,
        // bottom
        0, -1, 0,
        0, -1, 0,
        0, -1, 0,
        0, -1, 0
    ]),
    idx = new Uint32Array([
        // front
        0, 1, 2,
        3, 2, 1,
        // right
        4, 5, 6,
        7, 6, 5,
        // back
        8, 9, 10,
        11, 10, 9,
        // left
        12, 13, 14,
        15, 14, 13,
        // top
        16, 17, 18,
        19, 18, 17,
        // bottom
        20, 21, 22,
        23, 22, 21
    ]);

    var sideColors = new THREE.MultiMaterial([
        new THREE.MeshLambertMaterial({ color: 'red' }), // front
        new THREE.MeshLambertMaterial({ color: 'green' }), // right
        new THREE.MeshLambertMaterial({ color: 'orange' }), // back
        new THREE.MeshLambertMaterial({ color: 'blue' }), // left
        new THREE.MeshLambertMaterial({ color: 'white' }), // top
        new THREE.MeshLambertMaterial({ color: 'yellow' }) // bottom
    ]);

    var cubeGeometry = new THREE.BufferGeometry();
    cubeGeometry.addAttribute("position", new THREE.BufferAttribute(pos, 3));
    cubeGeometry.addAttribute("normal", new THREE.BufferAttribute(nor, 3));
    cubeGeometry.setIndex(new THREE.BufferAttribute(idx, 3));
    cubeGeometry.clearGroups();
    cubeGeometry.addGroup(0, 6, 0);
    cubeGeometry.addGroup(6, 6, 1);
    cubeGeometry.addGroup(12, 6, 2);
    cubeGeometry.addGroup(18, 6, 3);
    cubeGeometry.addGroup(24, 6, 4);
    cubeGeometry.addGroup(30, 6, 5);

    THREE.ColorCube = function (scaleX, scaleY, scaleZ) {
        THREE.Mesh.call(this, cubeGeometry, sideColors);
        var scaler = new THREE.Matrix4().makeScale(scaleX, scaleY, scaleZ);
        this.applyMatrix(scaler);
    };
    THREE.ColorCube.prototype = Object.create(THREE.Mesh.prototype);
    THREE.ColorCube.prototype.constructor = THREE.ColorCube;

    THREE.ColorCube.prototype.clearVertexNormals = function () {
        if (this.vNormals === undefined) {
            this.vNormals = [];
        }
        for (var i = 0, len = this.vNormals.length; i < len; ++i) {
            this.parent.remove(this.vNormals[i]);
        }
        this.vNormals.length = 0;
    }
    THREE.ColorCube.prototype.drawVertexNormals = function (scale, color) {
        this.clearVertexNormals();
        scale = (scale === undefined) ? 1 : scale;
        color = (color === undefined) ? 0xff : color;
        var origin = new THREE.Vector3(),
            normalArrow = null,
            vert = null,
            norm = null,
            index = null,
            vertexArray = this.geometry.attributes.position.array,
            normalArray = this.geometry.attributes.normal.array,
            indexArray = this.geometry.index.array;

        for (var i = 0, len = indexArray.length; i < len; ++i) {
            index = indexArray[i];
            vert = new THREE.Vector3(...vertexArray.slice((index * 3), (index * 3) + 3)).applyMatrix4(this.matrix);
            norm = new THREE.Vector3(...normalArray.slice((index * 3), (index * 3) + 3));

            normalArrow = new THREE.ArrowHelper(
                norm,
                origin,
                1 * scale,
                color,
                0.2 * scale,
                0.1 * scale
            );

            normalArrow.position.copy(vert);

            this.vNormals.push(normalArrow);
            this.parent.add(normalArrow);
        }
    };

    THREE.ColorCube.prototype.clearFaceNormals = function () {
        if (this.fNormals === undefined) {
            this.fNormals = [];
        }
        for (var i = 0, len = this.fNormals.length; i < len; ++i) {
            this.parent.remove(this.fNormals[i]);
        }
        this.fNormals.length = 0;
    }
    THREE.ColorCube.prototype.drawFaceNormals = function (scale, color) {
        this.clearFaceNormals();
        scale = (scale === undefined) ? 1 : scale;
        color = (color === undefined) ? 0xffaa00 : color;
        var origin = new THREE.Vector3(),
            normalArrow = null,
            vertices = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()],
            normals = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()],
            indices = [0, 0, 0],
            centroid = new THREE.Vector3(),
            faceNormal = new THREE.Vector3(),
            vertexArray = this.geometry.attributes.position.array,
            normalArray = this.geometry.attributes.normal.array,
            indexArray = this.geometry.index.array;

        for (var i = 0, len = indexArray.length; i < len; i += 3) {
            indices = indexArray.slice(i, i + 3);

            vertices[0].set(...vertexArray.slice((indices[0] * 3), (indices[0] * 3) + 3)).applyMatrix4(this.matrix);
            vertices[1].set(...vertexArray.slice((indices[1] * 3), (indices[1] * 3) + 3)).applyMatrix4(this.matrix);
            vertices[2].set(...vertexArray.slice((indices[2] * 3), (indices[2] * 3) + 3)).applyMatrix4(this.matrix);

            normals[0].set(...normalArray.slice((indices[0] * 3), (indices[0] * 3) + 3));
            normals[1].set(...normalArray.slice((indices[1] * 3), (indices[1] * 3) + 3));
            normals[2].set(...normalArray.slice((indices[2] * 3), (indices[2] * 3) + 3));

            centroid.set(
                (vertices[0].x + vertices[1].x + vertices[2].x) / 3,
                (vertices[0].y + vertices[1].y + vertices[2].y) / 3,
                (vertices[0].z + vertices[1].z + vertices[2].z) / 3
            );

            faceNormal.set(
                (normals[0].x + normals[1].x + normals[2].x) / 3,
                (normals[0].y + normals[1].y + normals[2].y) / 3,
                (normals[0].z + normals[1].z + normals[2].z) / 3
            );
            faceNormal.normalize();

            normalArrow = new THREE.ArrowHelper(
                faceNormal,
                origin,
                1 * scale,
                color,
                0.2 * scale,
                0.1 * scale
            );

            normalArrow.position.copy(centroid);

            this.fNormals.push(normalArrow);
            this.parent.add(normalArrow);
        }
    };

    THREE.ColorCube.prototype.clearAllNormals = function () {
        THREE.ColorCube.prototype.clearVertexNormals();
        THREE.ColorCube.prototype.clearFaceNormals();
    }

    THREE.ColorCube.prototype.drawWireframe = function (color) {
        if (this.wireframe === undefined) {
            color = (color === undefined) ? 0 : color;
            this.wireframe = new THREE.WireframeHelper(this, color);
            this.parent.add(this.wireframe);
        }
    }

    THREE.ColorCube.prototype.clearWireframe = function () {
        if (this.wireframe) {
            this.parent.remove(this.wireframe);
            delete this.wireframe;
        }
    }

})();

var cc = new THREE.ColorCube(25, 25, 25);
scene.add(cc);

cc.drawVertexNormals(25);
cc.drawFaceNormals(25);
cc.drawWireframe(0xffffff);
draw();

【问题讨论】:

    标签: three.js


    【解决方案1】:

    您设置的索引错误。 每个顶点有 1 个索引。但是,您的代码显示每个顶点有 3 个索引,这是没有意义的。

    如果你改变了

    cubeGeometry.setIndex(new THREE.BufferAttribute(idx, 3));
    

    cubeGeometry.setIndex(new THREE.BufferAttribute(idx, 1));
    

    你的问题解决了。

    这是工作的jsfiddle

    【讨论】:

    • 我不敢相信我错过了这么明显的错误。谢谢!
    • @TheJim01 不用担心。 80% 的时候这对我来说是一个明显的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    相关资源
    最近更新 更多