Threejs: Draw quad mesh - three.js

I am working on project where the app needs to show quad elements in wifeframe ( quad elements count could be in thousands) and also be able to pick the quad elements. I used 2 face3 to generate a quad, this results in a diagonal edge between the trias. What is a good solution to create quad element
squareGeometry = new THREE.Geometry();
squareGeometry.vertices.push(new THREE.Vector3(-1.0, 1.0, 0.0));
squareGeometry.vertices.push(new THREE.Vector3( 1.0, 1.0, 0.0));
squareGeometry.vertices.push(new THREE.Vector3( 1.0, -1.0, 0.0));
squareGeometry.vertices.push(new THREE.Vector3(-1.0, -1.0, 0.0));
squareGeometry.faces.push(new THREE.Face3(0, 1, 2));
squareGeometry.faces.push(new THREE.Face3(0, 3, 2));
material = new THREE.MeshBasicMaterial({color: 0x999999, specular: 0x101010, side: THREE.DoubleSide, wireframe: true});
mesh = new THREE.Mesh( squareGeometry, material );
scene.add(mesh)
Update :
The suggestions on Three.JS wireframe material - all polygons vs. just edges helps to create wireframe for hard edges. How about for shared edges. Below is a image with four QUAD elements, as seen only the free edges/hard edges are shown in wireframe
Note : I am using JsonLoader to load a Json file which has QUAD faces and vertices defining them
Is going towards custom shader a better option to hide the diagonal lines?
4 Quad Shaded
var material = new THREE.MeshPhongMaterial( {
color: 0xeee000,
opacity: 0.5,
transparent: true,
side: THREE.DoubleSide,
shading: THREE.FlatShading,
polygonOffset: true,
polygonOffsetFactor: 1,
polygonOffsetUnits: 1
} );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
var geo = new THREE.EdgesGeometry( mesh.geometry);
var mat = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 1 } );
var wireframe = new THREE.LineSegments( geo, mat );
mesh.add( wireframe );

Related

Drawing a plane in ThreeJS with Point and Normal Vector

I would like to draw a plane in ThreeJS with a point (e. g. 0, 10, 20) and a normal vector for the plane orientation. I simply just do no get the position or the orientation right. Please help me out. Regards
Here are two ways I've tried (with PlaneHelper):
const plane = new THREE.Plane(new THREE.Vector3(10, 10, 10), 3)
// does not work: planeObj.translate(new THREE.Vector3(100, 100, 100))
const helper = new THREE.PlaneHelper(plane, 50, 0x00ffff);
this.scene.add( helper )
Or without the PlaneHelper:
const geometry = new THREE.PlaneGeometry( 50, 50, 32 );
geometry.translate(100, 0, 0)
const material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
const plane = new THREE.Mesh( geometry, material );
scene.add( plane );
// normal orientation missing

Three.js how to add circle in center of scene

I work with sphere image and use for it Three.js and I need to add some small object like aim in center of the sphere, and when I will move scene this object should be always in center of scene.
var cubeGeometry = new THREE.CircleGeometry(2, 100);
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, side: THREE.DoubleSide, transparent: true, opacity: 0.5, depthTest: false});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
this.camera.add(cube)
cube.position.set( 0, 0, -55 );
you can add the aim to the sphere and it will move with it in the middle:
sphere.add(aim);

THREE.BufferGeometry - How do I manually set face colors?

I have a BufferedGeometry for which I would like to set color per face. However, as I understand, the color attribute on the geometry sets color per vertex, not face.
I tried using it anyhow by setting the coloring scheme on the material to be per face, material.vertexColors = THREE.FaceColors; and putting a Float32Array color attribute with 3 items per face (RGB, each ranging from 0 to 1). This did not have the desired output.
You want to assign face colors when using BufferGeometry. To do so, do the following:
Use non-indexed BufferGeometry.
Add a color attribute.
geometry.setAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
In the color attribute, assign all three vertices of each face to have the same color.
If you are using a three.js built-in material, in the material definition, set
vertexColors: true
If you are using ShaderMaterial, then you will have to write the shader yourself.
three.js r.146
Use MeshFaceMaterial for as many faces as you have. As an example, this material would be for an object with 6 sides:
var material = new THREE.MeshFaceMaterial([
new THREE.MeshBasicMaterial({
color: 0x00ff00
}),
new THREE.MeshBasicMaterial({
color: 0xff0000
}),
new THREE.MeshBasicMaterial({
color: 0x0000ff,
}),
new THREE.MeshBasicMaterial({
color: 0xffff00
}),
new THREE.MeshBasicMaterial({
color: 0x00ffff
}),
new THREE.MeshBasicMaterial({
color: 0xff00ff
})
]);
The code would look something like this.
var nCoordsComponents = 3; // x,y,z
var nColorComponents = 3; // r,g,b
var nFaces = 6; // e.g. for a pyramid
var nVerticesPerFace = 3; // Triangle faces
// Non-indexed arrays which have to be populated with your data.
var vertices = new Float32Array(nFaces*nVerticesPerFace*nCoordsComponents);
var colors = new Float32Array(nFaces*nVerticesPerFace*nColorComponents);
var bufferGeometry = new THREE.BufferGeometry();
bufferGeometry.addAttribute('position', new THREE.Float32BufferAttribute(pve, nCoordsComponents));
bufferGeometry.addAttribute('color', new THREE.Float32BufferAttribute(colors, nColorComponents));
var material = new THREE.MeshBasicMaterial ({vertexColors: THREE.VertexColors});
var mesh = new THREE.Mesh (bufferGeometry, material);
scene = new THREE.Scene();
scene.add(mesh);
See a full working example here.
const geom = new THREE.BufferGeometry();
const vertices = new Float32Array([
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0
]);
const colors = new Float32Array([
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
]);
geom.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geom.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.MeshBasicMaterial({vertexColors: true});
const mesh = new THREE.Mesh(geom, material);

2 of the same planes in a group, both aren't transparent

I have a plane mesh and I duplicated them and put them in a Object3d group, and they are both suppose to be transparent, but only one of them is, please help.
face = new THREE.MeshBasicMaterial({
side: THREE.DoubleSide,
transparent: true,
map: THREE.ImageUtils.loadTexture('face.png')
});
face.map.magFilter = THREE.NearestFilter;
face.map.minFilter = THREE.NearestFilter;
facePlane = new THREE.Mesh(new THREE.PlaneGeometry(100, 100), face);
faceGroup = new THREE.Object3D();
faceGroup.add(facePlane.clone());
faceGroup.add(facePlane.clone());
faceGroup.children[0].rotation.y = 90*(Math.PI/180);
scene.add(faceGroup);
Found a Solution on Three.js / WebGL - transparent planes hiding other planes behind them
adding alphaTest: 0.5 to the material.

Different material on back and frontside of extruded shape

I'm trying to apply different material on front and back sides of extruded shape, but cannot figure out where to put side: THREE.FrontSide and side: THREE.BackSide. Where they should be putted?
My relevant code part is:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture });
var materialSide = new THREE.MeshPhongMaterial({color: 0xE68A00, ambient: 0xffffff});
var extrusionSettings = {
amount: 10,
bevelEnabled: false,
bevelThickness: 0.2,
bevelSize: 0.2,
bevelSegments: 8,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shapes, extrusionSettings);
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
UPDATE:
According to WestLangley's comment I succeeded in adding the different texture to backfaces:
// ...
var materials = [materialFront, materialSide, materialBack];
// ...
for ( var face in mesh.geometry.faces ) {
if (mesh.geometry.faces[ face ].normal.z == 1) mesh.geometry.faces[ face ].materialIndex = 2;
}
After you create your mesh geometry, and before the first call to render(), you have to change the materialIndex to 2 for the back faces. Then, add a third material in your material array.
You can identify the back faces by their face normals. Face normals for faces on the back of the geometry should all point in the same direction.
three.js r.58
Try using:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture, side: THREE.FrontSide });
var materialSide = new THREE.MeshPhongMaterial({ color: 0xE68A00, ambient: 0xffffff, side: THREE.BackSide });
even though you should probably lower your ambient contribution and give a color to the FrontSide material.
Then:
var materials = [materialFront, materialSide];
scene.add( THREE.SceneUtils.createMultiMaterialObject( geometry, materials ));

Resources