How to add faces to THREE.BufferGeometry?

北战南征 提交于 2019-12-10 23:43:00

问题


I have created programmatically a simple mesh:

var CreateSimpleMesh = new function () {
    var xy = [],
        maxX = 7,
        maxY = 10,
        river = [[0, 5], [0, 4], [1, 3], [2, 2], [3, 2], [4, 1], [5, 1], [6, 0]],
        grassGeometry = new THREE.BufferGeometry(),
        grassVertexPositions = []

    this.init = function () {
        for (i = 0; i < maxX; i++) {
            for (j = 0; j < maxY; j++) {
                xy.push([i, j])
            }
        }

        for (var i = 0; i < xy.length; i++) {
            grassVertexPositions.push([xy[i][0], xy[i][1], 0])
            grassVertexPositions.push([xy[i][0] + 1, xy[i][1], 0])
            grassVertexPositions.push([xy[i][0], xy[i][1] + 1, 0])

            grassVertexPositions.push([xy[i][0] + 1, xy[i][1] + 1, 0])
            grassVertexPositions.push([xy[i][0], xy[i][1] + 1, 0])
            grassVertexPositions.push([xy[i][0] + 1, xy[i][1], 0])
        }

        for (var i = 0; i < grassVertexPositions.length; i++) {
            for (var j = 0; j < river.length; j++) {
                if (river[j][0] == grassVertexPositions[i][0] && river[j][1] == grassVertexPositions[i][1]) {
                    grassVertexPositions[i][2] = -0.5
                }
            }
        }

        var grassVertices = new Float32Array(grassVertexPositions.length * 3)

        for (var i = 0; i < grassVertexPositions.length; i++) {
            grassVertices[i * 3 + 0] = grassVertexPositions[i][0];
            grassVertices[i * 3 + 1] = grassVertexPositions[i][1];
            grassVertices[i * 3 + 2] = grassVertexPositions[i][2];
        }

        grassGeometry.addAttribute('position', new THREE.BufferAttribute(grassVertices, 3))

    var grassMaterial = new THREE.MeshLambertMaterial({color: 0x00ff00}),
        grassMesh = new THREE.Mesh(grassGeometry, grassMaterial)

        grassMesh.rotation.x = -Math.PI / 2
        Test.getScene().add(grassMesh);
    }
}

Problem is that this mesh has only vertices. I have tried to add to it faces like in this question using THREE.Shape.Utils.triangulateShape but BufferGeometry is different than normal geometry and it does not work. Is it possible to add faces to BufferGeometry?

EDIT: Working fiddle


回答1:


Here is how to create a mesh having BufferGeometry. This is the simpler "non-indexed" BufferGeometry where vertices are not shared.

// non-indexed buffer geometry
var geometry = new THREE.BufferGeometry();

// number of triangles
var NUM_TRIANGLES = 10;

// attributes
var positions = new Float32Array( NUM_TRIANGLES * 3 * 3 );
var normals   = new Float32Array( NUM_TRIANGLES * 3 * 3 );
var colors    = new Float32Array( NUM_TRIANGLES * 3 * 3 );
var uvs       = new Float32Array( NUM_TRIANGLES * 3 * 2 );

var color = new THREE.Color();
var scale = 15;
var size = 5;
var x, y, z;

for ( var i = 0, l = NUM_TRIANGLES * 3; i < l; i ++ ) {

    if ( i % 3 === 0 ) {

        x = ( Math.random() - 0.5 ) * scale;
        y = ( Math.random() - 0.5 ) * scale;
        z = ( Math.random() - 0.5 ) * scale;

    } else {

        x = x + size * ( Math.random() - 0.5 );
        y = y + size * ( Math.random() - 0.5 );
        z = z + size * ( Math.random() - 0.5 );

    }

    var index = 3 * i;

    // positions
    positions[ index     ] = x;
    positions[ index + 1 ] = y;
    positions[ index + 2 ] = z;

    //normals -- we will set normals later

    // colors
    color.setHSL( i / l, 1.0, 0.5 );
    colors[ index     ] = color.r;
    colors[ index + 1 ] = color.g;
    colors[ index + 2 ] = color.b;

    // uvs
    uvs[ index     ] = Math.random(); // just something...
    uvs[ index + 1 ] = Math.random();

}

geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

// optional
geometry.computeBoundingBox();
geometry.computeBoundingSphere();

// set the normals
geometry.computeVertexNormals(); // computed vertex normals are orthogonal to the face for non-indexed BufferGeometry

fiddle: http://jsfiddle.net/5co6c27w/

See the three.js examples for many additional examples of creating BufferGeometry. Also check out the source code for PlaneBufferGeometry and SphereBufferGeometry, which are reasonably easy to understand.

three.js r.73




回答2:


You can add faces using three.js internal function- fromBufferGeometry. In your case it would be something like this.

var directGeo = new THREE.Geometry();
directGeo.fromBufferGeometry(grassGeometry);

Then use directGeo to build your mesh, and it will have faces.



来源:https://stackoverflow.com/questions/34147202/how-to-add-faces-to-three-buffergeometry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!