Multple Cubes with different materials in three.js - javascript

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.

Related

Multiple STL files on single web page using threeJS

Here I have one STL file that I am displaying with threeJS. I don't know how to render multiple STL Files in single web page.
Here's my code:
var container, camera, scene, renderer;
init();
animate();
function init() {
container = document.getElementById('pratik');
document.body.appendChild( container );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 3, 0.5, 3 );
scene.add( camera ); // required, because we are adding a light as a child of the camera
// Controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
// lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
var light = new THREE.PointLight( 0xffffff, 0.8 );
camera.add( light );
// object
var loader = new THREE.STLLoader();
loader.load( 'files/wolf.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var timer = Date.now() * 0.0005;
camera.position.x = Math.cos( timer ) * 15;
camera.position.z = Math.sin( timer ) * 15;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
<div id="pratik"></div>
Now what if I need to include another file named 'mk6.stl', How will I do it?
Does anyone knows how to do it?
I have tried SketchFan, but its not made for me.
Thank you.
You already have the code to load a single STL file and insert it into your scene. The next step to load multiple files is straightforward, you would simply reuse your STLLoader instance. Basically you could do something like:
var loader = new THREE.STLLoader();
loader.load( 'FIRSTFILE.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
loader.load( 'SECONDFILE.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xff5533 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
} );
You could also use the loaders load() method in a loop if you have an array of URLs to load your STL-files from.

THREE.js LineSegments with multimaterial support

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

Three.js Make static cube

I'm newbie in Three.js, so, I'm trying just to make STATIC cube. So, I've found a rotating cube example. Here it is:
var camera, scene, renderer;
var mesh;
init();
animate();
//renderer.render( scene, camera );
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( '16.jpg' );
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var axes = new THREE.AxisHelper( 20 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render( scene, camera );
}
ok, everything work fine. Now I want to make just STATIC cube, I've wrote
var camera, scene, renderer;
var mesh;
init();
renderer.render( scene, camera );
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
var texture = THREE.ImageUtils.loadTexture( '16.jpg' );
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var axes = new THREE.AxisHelper( 20 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
The output is just a black screen, what have I done wrong?
The texture loading is asynchronous, and you are rendering the scene before it is done.
Add a callback to the Image Loader and render again:
var texture = THREE.ImageUtils.loadTexture('16.jpg', undefined, function () {
renderer.render(scene, camera);
});
Alternatively render continuosly with requestAnimationFrame:
init();
animate();
//...
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
it looks like when you got rid of animate(), you also got rid of the call to
renderer.render( scene, camera );
so you need to put that back in the code somewhere to render your scene

Create a unique sphere geometry from a sphere and a cylinder Three.js

I'm trying to create a bead like object in Three.js, essentially a sphere with a cylinder through it. I can create the two independently, but I'm wondering how to match the height of the sphere and the cylinder and how to merge / intersect them, so that the result will be one geometry.
Any ideas?
Thanks!
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//material
var material = new THREE.MeshNormalMaterial( {
wireframe: true
} );
//sphere
var sphere = new THREE.SphereGeometry(2,20,20);
var sphereMesh = new THREE.Mesh( sphere, material );
scene.add( sphereMesh );
//cyl
var cylinder = new THREE.CylinderGeometry(0.5, 0.5, 2, 32 );
var cylinderMesh = new THREE.Mesh( cylinder, material );
scene.add( cylinderMesh );
camera.position.x = 0;
camera.position.y = 0;
camera.position.z = 5;
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
http://jsfiddle.net/RqU2v/
#gaitat, totally awesome, thanks.
here's the solution with ThreeCSG:
//sphere
var sphere = new THREE.SphereGeometry(2,20,20);
var sphereMesh = new THREE.Mesh( sphere, material );
var sphereBSP = new ThreeBSP( sphereMesh );
//cyl
var cylinder = new THREE.CylinderGeometry(0.5, 0.5, 5, 32 );
var cylinderMesh = new THREE.Mesh( cylinder, material );
var cylinderBSP = new ThreeBSP( cylinderMesh );
//result
var subtract_bsp = sphereBSP.subtract( cylinderBSP );
var result = subtract_bsp.toMesh( material );
result.geometry.computeVertexNormals();
scene.add( result );

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