Three.js how to add circle in center of scene - three.js

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);

Related

MeshPhongMaterial or MeshStandardMaterial does not give me the expected output with metallic look

I have the following lights, the ambient light and one PointLight attached to the camera.
this.ambientLight = new THREE.AmbientLight(0xffffff, 0.9);
var pointLight = new THREE.PointLight(0xffffff, 1);
//add to the camera/scene
this.camera.add(pointLight);
this.scene.add(this.ambientLight);
And I'm using the following meshes that I'm trying to give a metallic look, a sphere and a custom mesh that appears like a beam (here the code is simplified)!
//sphere
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10, 10, 10), material2);
//custom mesh
const shape = new THREE.Shape();
shape.moveTo(0,0);
shape.lineTo(0,1);
shape.lineTo(1,1);
shape.lineTo(1,0);
shape.lineTo(0,0);
const extrudeSettings = {
steps: width, // ui: steps
depth: width, // ui: depth
};
var geom = new THREE.ExtrudeGeometry(shape, extrudeSettings);
var beam = new THREE.Mesh(geom , material);
And I've tested with the following materials:
const material = new THREE.MeshPhongMaterial(
{
flatShading: true,
emissive: 'grey',
color: 'grey',
shininess: 150,
side: THREE.DoubleSide,
});
const material2 = new THREE.MeshStandardMaterial({
metalness: 1,
emissive: 'grey',
color: 'grey',
side: THREE.DoubleSide,
flatShading: true,
});
I've tried messing around with the materials settings, but no luck! I want to obtain a metal finishing look, with shadows/depth, ideally using the MeshPhongMaterial!
At the moment, it looks like this:
Am I doing anything wrong with the lightning or with the materials?

How to put a transparent color mask on a 3D object in three.js?

I've been trying to 'submerge' a 3D object in a semi-transparent 3D plane of water (without the whole water plane showing), and after having experimented with custom blending modes for hours, I don't really get how to do it.
Fiddle here: https://jsfiddle.net/mglonnro/p2ju4qbk/34/
var camera, scene, renderer, geometry, material, mesh,
surface_geometry, surface_material, surface_mesh,
bottom_geometry, bottom_material, bottom_mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 200, 500);
camera.lookAt(0, 0, 0);
scene.add(camera);
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
bottom_geometry = new THREE.PlaneBufferGeometry(10000, 10000);
bottom_material = new THREE.MeshBasicMaterial({
color: 0xFFAAAA,
side: THREE.DoubleSide
});
bottom_mesh = new THREE.Mesh(bottom_geometry, bottom_material);
bottom_mesh.rotation.set(Math.PI / 2, 0, 0);
bottom_mesh.position.set(0, -200, 0);
scene.add(bottom_mesh);
surface_geometry = new THREE.PlaneBufferGeometry(400, 400);
surface_material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6
});
surface_mesh = new THREE.Mesh(surface_geometry, surface_material);
surface_mesh.rotation.set(Math.PI / 2, 0, 0);
scene.add(surface_mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
renderer.render(scene, camera);
}
The cube is submerged, as it should be, and the parts covered by the transparent water look like I want them to look.
The problem, however, is that I want ONLY the cube and its submerged parts to be rendered, NOT the rest of the water plane.
In other words:
There are three objects in the scene:
the redish "bottom" farthest away
the cube, partly above, partly
below the water
the water
Is there some way to blend these together so that the water pixels are rendered only when they are on top of a cube pixel, not when they are just on top of the background/bottom?
EDIT: SOLUTION
Add stencil write functionality to the cube:
const stencilId = 1;
geometry = new THREE.CubeGeometry(200, 200, 200);
material = new THREE.MeshNormalMaterial({
stencilWrite: true,
stencilFunc: THREE.AlwaysStencilFunc,
stencilZPass: THREE.ReplaceStencilOp,
stencilRef: stencilId
});
Add stencil test functionality to the surface:
surface_material = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6,
stencilWrite: true,
stencilFunc: THREE.EqualStencilFunc,
stencilRef: stencilId
});
Realize that the three.js version in jsfiddle is too old to support stencils and move to codepen :)
Stencil Test is a natural way to achieve that.
All objects which should have water on top of them write some stencil value.
Water plane has stencil test set to this value.
three.js has stencil example, but it uses IncrementWrap and DecrementWrap logic which is not needed for your case.
I recommend trying ReplaceStencilOp for cube and EqualStencilFunc for water.

Threejs: Draw quad mesh

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 );

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