THREE.js LineSegments with multimaterial support - javascript

In my project I am creating LineSegments (LineMesh) with modified geometry (changing the vertex positions) from another mesh and with MeshBasicMaterialwith black color.Adding the LineMesh to the already existing Mesh.
Everything works fine.
But now I want to hide particular part of the mesh by setting visible property to false by taking the materialIndex from the faces of geometry.But in this, the previously created mesh is hiding but LineMesh added to it is not hiding.
Is it possible to hide particular part of LineMesh and also wanted to know whether LineMesh will support MultiMaterial.So that it will be easy for me to apply visibility, transparent property to particular part of Mesh.
var mesh, renderer, scene, camera, materials;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 300;
camera.lookAt( scene.position );
// directional
var light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
// ambient
var ambient = new THREE.AmbientLight( 0x222222 );
scene.add( ambient );
// geometry
var geometry = new THREE.BoxGeometry( 100, 100, 100, 4, 4, 4 );
// materials
materials = [
new THREE.MeshLambertMaterial( { color: 0xffff00, side: THREE.DoubleSide } ),
new THREE.MeshBasicMaterial( { color: 0x00ffff, side: THREE.DoubleSide } )
];
// assign material to each face
for( var i = 0; i < geometry.faces.length; i++ ) {
geometry.faces[ i ].materialIndex = THREE.Math.randInt( 0, 1 );
}
geometry.sortFacesByMaterialIndex(); // optional, to reduce draw calls
// mesh
mesh = new THREE.Mesh( geometry, materials );
scene.add( mesh );
mat = new THREE.LineBasicMaterial({color: 0x000000});
mesh2= new THREE.LineSegments(geometry, mat);
mesh.add(mesh2);
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
mesh.rotation.z += 0.03;
renderer.render( scene, camera );
}
This below code is not to be working for LineSegments
mesh2= new THREE.LineSegments(geometry, new THREE.MultiMaterial(materials));

Related

How to calculate the position of objects in Three.js

I am new to 3D Graphics programming. I'm using Three.js to design a software that uses 3D visualisation for 3D bin packaging. Right now I'm using the below code to create and position two elements.
var camera, scene, renderer;
var mesh, mesh2;
init();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 800;
scene = new THREE.Scene();
var texture = new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/crate.gif' );
var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var geometry2 = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( {map:texture} );
mesh = new THREE.Mesh( geometry, material );
mesh2 = new THREE.Mesh( geometry2, material );
mesh2.position.x = 170
mesh2.position.y = -48
mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
mesh2.rotation.x = 0.45;
mesh2.rotation.y = 1;
scene.add( mesh2 );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
Right now I'm using (170, -48, 100) as the coordinates to align the second cube. I've arrived to these numbers by tweaking the numbers and constantly checking. But there should be some formula to get these x,y,z since I'm rotating them to a certain angle (x=0.45, y=1). I'm not sure how to start the calculation for this.
The problem statement is, given a set of cubes dimensions' (l1, w1, h1), (h2, w2, h2) and so on and cubes positions (x1, y1, z1) (x2, y2, z2) how to calculate and place them near and/or stack them?
Make mesh2 a child of mesh: mesh.add( mesh2 )
mesh2 will inherit rotation of mesh and you will define relative offsets to shift it in coordinate space of parent.
Fixed example:
mesh = new THREE.Mesh( geometry, material );
mesh2 = new THREE.Mesh( geometry2, material );
mesh2.position.x = 170
//mesh2.position.y = -48
//mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
//mesh2.rotation.x = 0.45;
//mesh2.rotation.y = 1;
scene.add( mesh );
mesh.add( mesh2 ); // << ---- solution
Updated: Also possible without parent-child hierarchy.
let mesh = new THREE.Mesh( geometry, material );
let mesh2 = new THREE.Mesh( geometry2, material );
// mesh2.position.x = 170
// mesh2.position.y = -48
// mesh2.position.z = 100
mesh.rotation.x = 0.45;
mesh.rotation.y = 1;
mesh.updateMatrix(); // <<-- this is essential, to write .position and .rotation values into object transformation matrix.
// mesh2.rotation.x = 0.45;
// mesh2.rotation.y = 1;
scene.add( mesh );
// apply local transforms
mesh2.applyMatrix(new THREE.Matrix4().makeTranslation(210, 0, 0));
// apply transforms of mesh on top
mesh2.applyMatrix(mesh.matrix);
scene.add( mesh2 ); // << ---- add directly to Scene

Multple Cubes with different materials in three.js

I'm teaching myself three.js and am playing around with different materials on cubes. I'm trying to add 3 cubes to a scene, each with a different material, to compare differences side by side.
The issue is that only cube1 currently renders. The other cubes do not appear in the browser. Any help in fixing the issue would be greatly appreciated.
<body>
<script src="../three.js-master/build/three.min.js"></script>
<script src="../three.js-master/examples/js/controls/OrbitControls.js"></script>
<script>
var camera, scene, renderer;
var controls
var cube1, cube2, cube3;
init();
animate();
function init() {
//Renderer
renderer = new THREE.WebGLRenderer( {antialias: true} );
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize( width, height );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
//Create Cubes
//Normal
var cube1Geometry = new THREE.BoxGeometry( 2,1,1 );
var cube1Material = new THREE.MeshNormalMaterial();
cube1 = new THREE.Mesh( cube1Geometry, cube1Material );
cube1.position.set( 0,0,0 );
scene.add( cube1 );
//Lambert
var cube2Geometry = new THREE.BoxGeometry( 1,2,1 );
var cube2Material = new THREE.MeshLambertMaterial( {color: 0xff0000, transparent: true, opacity: 05} );
cube2 = new THREE.Mesh( cube2Geometry, cube2Material );
cube2.position.set( -10,0,0 );
scene.add( cube2 );
//Phong
var cube3Geometry = new THREE.BoxGeometry( 1,1,2 );
var cube3Material = new THREE.MeshPhongMaterial( {shininess: 1} );
cube3 = new THREE.Mesh( cube3Geometry, cube3Material );
cube3.position.set( 10,0,0 );
scene.add( cube3 );
//Create Camera
camera = new THREE.PerspectiveCamera (45, width/height, 1, 1000);
camera.position.y = 30;
camera.position.z = 30;
camera.lookAt( new THREE.Vector3( 0,0,0 ) );
controls = new THREE.OrbitControls( camera, renderer.domElement );
}
function animate() {
controls.update();
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
</script>
</body>
Continued digging into the issue brought to light (pun intended) that lambert and phong materials require a light source. They were both being rendered, but were not visible due to lack of light.
Added:
//Light Source
var light = new THREE.PointLight( 0xff0000, 1, 100 );
light.position.set( 20,20, 20 );
scene.add( light );
And they now appear in the browser.

Can't animate wireframe rotation in Three.js

I tried to make the wireframe rotate in the scene.
The animation works when I removed the BoxHelper, but I want to animate the cube wireframe without diagonal line instead of a solid object.
Codepen demo :
Demo
Code :
var w = window.innerWidth, h = window.innerHeight,
scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000),
renderer = new THREE.WebGLRenderer(),
geometry = new THREE.BoxGeometry( 1, 1, 1 ),
material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ),
mesh = new THREE.Mesh( geometry, material ),
cube = new THREE.BoxHelper(mesh);
cube.material.color.setRGB(25,25,25);
scene.add(cube);
camera.position.z = 2;
renderer.setSize(w,h);
document.body.appendChild(renderer.domElement);
function render(){
requestAnimationFrame( render );
cube.rotation.x += 1;
renderer.render(scene, camera );
}
render();
The position of your THREE.BoxHelper instance is tied to the position of the THREE.Mesh. For your code to work you will have to add the mesh to the scene and rotate the mesh. Your box helper will follow.
If you don't want to show the mesh you can simply set mesh.visible = false;
This code works:
var w = window.innerWidth, h = window.innerHeight,
scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(75, w/h, 0.1, 1000),
renderer = new THREE.WebGLRenderer(),
geometry = new THREE.BoxGeometry( 1, 1, 1 ),
mesh = new THREE.Mesh( geometry );
camera.position.z = 2;
renderer.setSize(w,h);
document.body.appendChild(renderer.domElement);
mesh.visible = false; //<-- hide mesh
scene.add(mesh); //<-- add mesh to scene
cube = new THREE.BoxHelper(mesh);
cube.material.color.setRGB(25,25,25);
scene.add(cube);
function render(){
mesh.rotation.y += 0.01; //<-- rotate the mesh
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();

Mesh only visible in reflection

I'm using a cubeCamera for live cube maps reflections.
How do I show a mesh only in the reflection.
Can anyone guide me how to accomplish it, or is it possible at all ?
cubeCamera = new THREE.CubeCamera( 1, 600, 512 );
cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
scene.add( cubeCamera );
envMap
envMap: cubeCamera.renderTarget,
Basic mesh
var geometry = new THREE.PlaneBufferGeometry( 1, 1 );
var material = new THREE.MeshBasicMaterial({color: 0xffffff });
var mesh = new THREE.Mesh( geometry, material);
mesh.position.set( 0, 0, 0 );
scene.add( mesh );
Render
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function render() {
cubeCamera.updateCubeMap( renderer, scene );
renderer.render( scene, camera );
}
function update() {
requestAnimationFrame( update );
render();
}
Try this (I have not tested it)
I am assuming it is the mesh object that you want only visible in the reflections.
Basic mesh
var geometry = new THREE.PlaneBufferGeometry( 1, 1 );
var material = new THREE.MeshBasicMaterial({color: 0xffffff });
var mesh = new THREE.Mesh( geometry, material);
mesh.position.set( 0, 0, 0 );
// make your mesh invisible.
mesh.visible = false;
scene.add( mesh );
Render
function render() {
// Make mesh visible to the cubeCamera.
mesh.visible = true;
cubeCamera.updateCubeMap( renderer, scene );
// Make mesh invisible again.
mesh.visible = false;
renderer.render( scene, camera );
}

Coloring individual faces of shape in three.js

I'm extending a simple example which displays a rotating cube, I'd like to change the colour of individual faces, but not having any luck. What's wrong with this code? Thanks
$(function(){
var camera, scene, renderer,
geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 800;
geometry = new THREE.CubeGeometry( 500, 70, 70 );
material_1 = new THREE.MeshBasicMaterial( {
color: 0xff0000,
shading: THREE.FlatShading,
overdraw: true
} );
material_2 = new THREE.MeshBasicMaterial( {
color: 0x00ff00,
shading: THREE.FlatShading,
overdraw: true
} );
geometry.materials = [material_1, material_2];
geometry.faces[0].materialIndex = 0;
geometry.faces[1].materialIndex = 1;
geometry.faces[2].materialIndex = 0;
geometry.faces[3].materialIndex = 1;
geometry.faces[4].materialIndex = 0;
geometry.faces[5].materialIndex = 1;
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
scene.add( mesh );
renderer = new THREE.CanvasRenderer();
renderer.setClearColorHex(0x000000, 1);
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.05;
renderer.render( scene, camera );
}
});
You need to pass an array of materials to the MeshFaceMaterial constructor as an argument.
Instead of:
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
You should have:
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( geometry.materials ) );

Categories

Resources