Adding indices to a BufferGeometry does not work? - javascript

I have been trying to draw a very basic rectangle using THREE.BufferGeometry(). Here is the code -
var geometry = new THREE.BufferGeometry();
var material = new THREE.MeshBasicMaterial({color: 'rgb(255, 0, 0)'});
var verticesArray = [20, 0, 0, 0, 20, 0, -20, 0, 0, 0, -20, 0];
var vertices = new Float32Array(verticesArray, 0, 12);
var indicesArray = [0, 1, 2, 0, 2, 3];
var indices = new Uint16Array(indicesArray, 0, 6);
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
//geometry.addAttribute('index', new THREE.BufferAttribute(indices, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 3));
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
Unfortunately it isn't working. It isn't throwing any exception either. To my understanding, i have done everything right. I have four vertices, and i have described two set of indices in counter clockwise order.
Could anyone please tell me what can go wrong here?

It should be geometry.setIndex(new THREE.BufferAttribute(indices, 1));

Related

Three.js texture streches when the width is large

You can see when the width is less the texture fits perfectly and when the wall is long it stretches.
const wallTex = new THREE.TextureLoader().load(wallTexture);
wallTex.encoding = THREE.sRGBEncoding;
wallTex.wrapS = THREE.RepeatWrapping;
wallTex.wrapT = THREE.RepeatWrapping;
wallTex.repeat.set(4, 1);
const wallMaterial = new THREE.MeshBasicMaterial({ map: wallTex, side: THREE.DoubleSide });
When I dont set texture.repeat.set(4,1) I get the result as below
Is there a way to add texture irrespective of its width?
const wallGeometry = new THREE.BufferGeometry();
const wallVertices = new Float32Array([
-x1,
y1,
0, // vertex 1
-x1,
y1,
10, // vertex 2
-x2,
y2,
0, // vertex 3
-x2,
y2,
10, // vertex 4
]);
// define texture coordinates for wallGeometry
const wallUvs = new Float32Array([
0,
0, // vertex 1
0,
1, // vertex 2
1,
0, // vertex 3
1,
1, // vertex 4
]);
wallGeometry.setAttribute('uv', new THREE.BufferAttribute(wallUvs, 2));
wallGeometry.setAttribute('position', new THREE.BufferAttribute(wallVertices, 3));
wallGeometry.setIndex([0, 2, 1, 2, 3, 1]);
const wall = new THREE.Mesh(wallGeometry, wallMaterial);
const geo = new THREE.EdgesGeometry(wall.geometry);
const wireframe = new THREE.LineSegments(geo, lineMaterial);
wall.add(wireframe);
wall.castShadow = true;
wall.receiveShadow = true;
scene!.add(wall);

I want to generate 2D octagon with Three.js

I get a peculiar triangle with this code while I am trying to generate a regular octagon:
var geom = new THREE.Geometry();
geom.vertices.push( new THREE.Vector3(100, 250, 0));
geom.vertices.push( new THREE.Vector3(250, 100, 0));
geom.vertices.push( new THREE.Vector3(250, -100, 0));
geom.vertices.push( new THREE.Vector3(100, -250, 0));
geom.vertices.push( new THREE.Vector3(-100, 250, 0));
geom.vertices.push( new THREE.Vector3(-250, -100, 0));
geom.vertices.push( new THREE.Vector3(-250, 100, 0));
geom.vertices.push( new THREE.Vector3(-100, 250, 0));
geom.faces.push( new THREE.Face3(0, 1, 2));
geom.faces.push( new THREE.Face3(0, 2, 3));
geom.faces.push( new THREE.Face3(0, 3, 4));
geom.faces.push( new THREE.Face3(0, 4, 5));
geom.faces.push( new THREE.Face3(0, 5, 6));
geom.faces.push( new THREE.Face3(0, 6, 7));
var material = new THREE.MeshBasicMaterial();
var mesh = new THREE.Mesh( geom, material);
mesh.position.set(0, 0, -1000);
scene.add(mesh);
Moreover one of the vertices of the generated triangle is placed somewhere I did not even mentioned in the code.
It is possible only the last added face is being shown, but I expect to see all the faces adjacent to each other forming a regular octagon.
So, order of vertices in a face is counter-clockwise, 5th and 8th points are different:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 500);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var geom = new THREE.Geometry();
geom.vertices.push(new THREE.Vector3(100, 250, 0));
geom.vertices.push(new THREE.Vector3(250, 100, 0));
geom.vertices.push(new THREE.Vector3(250, -100, 0));
geom.vertices.push(new THREE.Vector3(100, -250, 0));
geom.vertices.push(new THREE.Vector3(-100, -250, 0)); // y-coordinate is corrected
geom.vertices.push(new THREE.Vector3(-250, -100, 0));
geom.vertices.push(new THREE.Vector3(-250, 100, 0));
geom.vertices.push(new THREE.Vector3(-100, 250, 0));
geom.faces.push(new THREE.Face3(0, 2, 1)); // order of vertices
geom.faces.push(new THREE.Face3(0, 3, 2));
geom.faces.push(new THREE.Face3(0, 4, 3));
geom.faces.push(new THREE.Face3(0, 5, 4));
geom.faces.push(new THREE.Face3(0, 6, 5));
geom.faces.push(new THREE.Face3(0, 7, 6));
geom.computeFaceNormals();
geom.computeVertexNormals();
var material = new THREE.MeshBasicMaterial({
color: "white"
});
var mesh = new THREE.Mesh(geom, material);
scene.add(mesh);
var points = new THREE.Points(geom, new THREE.PointsMaterial({
size: 20,
color: 0xff0000
}));
scene.add(points); // just to visualize the points
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Randomize dots on sphere and give them ID

I try to create this sphere in three.js. I need clickable dotes and meshes. So I think, that I can do this if I will give name for every dot in sphere.
Two questions:
1. How I can randomize positions of dots on sphere?
2. How I should to give names for dots and meshes?
THREE.IcosahedronGeometry = function(radius, detail) {
var t = (1 + Math.sqrt(5)) / 2;
var vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0,
0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t,
t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0,
0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t,
t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1
];
var indices = [
2,10,6,0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
];
THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
this.type = 'IcosahedronGeometry';
this.parameters = {
radius: radius,
detail: detail
};
};
THREE.IcosahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry;
// Scene
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({
antialias: 1
});
renderer.setClearColor(0xf7f7f7);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.fog = new THREE.Fog(0xd4d4d4, 8, 20);
// Create vertex points
var mesh = new THREE.IcosahedronGeometry(10, 2); // radius, detail
var vertices = mesh.vertices;
var positions = new Float32Array(vertices.length * 3);
for (var i = 0, l = vertices.length; i < l; i++) {
vertices[i].toArray(positions, i * 3);
}
alert(positions);
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
var material = new THREE.PointsMaterial({
size: 0.4,
vertexColors: THREE.VertexColors,
color: 0x252525
});
var points = new THREE.Points(geometry, material);
var object = new THREE.Object3D();
object.add(points);
object.add(new THREE.Mesh(
mesh,
new THREE.MeshPhongMaterial({
color: 0x616161,
emissive: 0xa1a1a1,
wireframe: true,
fog: 1
})
));
scene.add(object);
camera.position.z = 20;
var render = function() {
requestAnimationFrame(render);
object.rotation.x += 0.001;
object.rotation.y += 0.001;
renderer.render(scene, camera);
};
render();
http://codepen.io/anon/pen/ZLpPxB
here is an example how you could randomize the points: http://codepen.io/usefulthink/pen/WRoboo?editors=0010
The interesting bit is this:
var v3 = new THREE.Vector3();
var spherical = new THREE.Spherical();
for (var i = 0; i < vertices.length; i += 3) {
v3.fromArray(vertices, i);
spherical.setFromVector3(v3);
spherical.phi += rnd(variation, -variation);
spherical.theta += rnd(variation, -variation);
v3.setFromSpherical(spherical);
v3.toArray(vertices, i);
}
In short, a good way to manipulate points on the surface of a sphere is to use spherical-coordinates (phi/theta/r instead of x/y/z, think latitude/longitude). In this case I convert each of the vertices into the spherical form, manipulate the theta/phi-values a bit (keeping the radius as it is) and write the modified values back to the vertices-array.
I am not sure what you mean with giving names to these points. Something like this?
var pointNames = {
frank: 12,
maria: 7,
steve: 3,
melissa: 4
};
function getPointByName(name) {
const startIndex = pointNames[name] * 3;
return new THREE.Vector3().fromArray(vertices, index);
}

Three.js - change face size on planeGeometry

I'm trying to change faces coordinates by modify the vertices.
The values of the variables are correct, but no change on the screen.
This is the plain
And this is my code :
var geometry = editor.selected.geometry;
var vertices = geometry.vertices;
vertices[1] = new THREE.Vector3(-100 / 3, 50, 0);
vertices[5] = new THREE.Vector3(-100 / 3, 0, 0);
var uvs = geometry.faceVertexUvs[0];
uvs[0] = [new THREE.Vector2(0, 1), new THREE.Vector2(0, 0.5), new THREE.Vector2(1 / 6, 1)];
uvs[1] = [new THREE.Vector2(0, 0.5), new THREE.Vector2(1 / 6, 0.5), new THREE.Vector2(1 / 6, 1)];
uvs[2] = [new THREE.Vector2(1 / 6, 1), new THREE.Vector2(1 / 6, 0.5), new THREE.Vector2(2 / 3, 1)];
uvs[3] = [new THREE.Vector2(1/ 6, 0.5), new THREE.Vector2(2 / 3, 0.5), new THREE.Vector2(2 / 3, 1)];
geometry.computeVertexNormals();
geometry.computeFaceNormals();
geometry.__dirtyVertices = true;
geometry.__dirtyNormals = true;
geometry.verticesNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.uvsNeedUpdate = true;
Any suggestions?
You are changing vertices that lie inside the border of the shape. Thats why you dont see a change. If you turn on wireframe on your material you will see that the vertices do change. Take a look at this fiddle:
http://jsfiddle.net/g6pzvjxj/
Also for your uvs it should be:
var uvs = geometry.faceVertexUvs[0];

Setting three.js projection matrix direction

I read following codes writing for webgl, and I want rewrite it using three.js. But I could not find any way to do so, please help me.
pMatrix = mat4.create();
mat4.perspective(pMatrix,1.01,gl.drawingBufferWidth/gl.drawingBufferHeight, 10.0, 300000.0);
var eciMat = [1, 0, 0, 0,
0, 0, -1, 0,
0, 1, 0, 0,
0, 0, 0, 1
];
mat4.mul(pMatrix, pMatrix, eciMat );
Matrix classes are pretty sophisticated in Three.js, look at the docs here: http://threejs.org/docs/#Reference/Math/Matrix4
Here's how I would write it in Three.js
// Arguments are fov, aspect, near, far
var perspectiveMatrix = new THREE.Matrix4().makePerspective(30, 1, 0.01, 20);
var eciMatrix = new THREE.Matrix4();
eciMatrix.set(1, 0, 0, 0,
0, 0, -1, 0,
0, 1, 0, 0,
0, 0, 0, 1);
var resultMatrix = new THREE.Matrix4();
resultMatrix.multiply(eciMatrix);
resultMatrix.multiply(perspectiveMatrix);
resultMatrix.multiply(perspectiveMatrix);
console.log(resultMatrix);

Categories

Resources