Reputation: 167
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
Upvotes: 5
Views: 6951
Reputation: 104763
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
See the three.js examples for many additional examples of creating BufferGeometry
. Also check out the source code for PlaneGeometry
and SphereGeometry
, which are reasonably easy to understand.
three.js r.143
Upvotes: 5
Reputation: 81
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.
Upvotes: 1