Three.js directional light shadow not working if object small - three.js

I am making an example of using light shadow. It works well, for example:
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
mesh = new THREE.Mesh(geometry, material);
mesh.position.y += 0.1;
mesh.castShadow = true;
scene.add(mesh);
Fiddle Link
However, when I reduce dimension of box from 0.1 to 0.01, the shadow disappears:
// Create cube and add to scene.
var geometry = new THREE.BoxGeometry(0.01, 0.01, 0.01);
mesh = new THREE.Mesh(geometry, material);
mesh.position.y += 0.01;
mesh.castShadow = true;
scene.add(mesh);
Fiddle Link
Can you tell me how can get shadow with small object?
Thank you.

Related

Three.js marker on mesh

I'm working on a visualization that uses a height map to create a 3d terrain, and want to add some markers for locations of cities on the map. I'm guessing some sort of raycaster and intersectObject might do it, but I'm lost as to how to place a marker directly on the surface of the terrain. For instance, I know that a city is at (640, 480) in the pixel units of my texture, so I'm doing something like:
// This is the terrain, loaded from a PNG of the digital elevation model
var planeGeo = new THREE.PlaneGeometry( bumpTexture.image.width, bumpTexture.image.height, 600, 450 );
var plane = new THREE.Mesh( planeGeo, customMaterial );
plane.rotation.x = -Math.PI / 2;
plane.position.y = 0;
scene.add( plane );
// At (640, 480) of the image, there should be a marker directly on top of the mesh.
var cube = new THREE.Mesh( new THREE.CubeGeometry( 20, 20, 20 ), new THREE.MeshNormalMaterial() );
cube.position.x = 640;
cube.position.y = 0;
cube.position.z = 480;
scene.add(cube);
raycaster.setFromCamera(cube, camera );
var intersects = raycaster.intersectObject(plane);
console.log(raycaster, intersects);
// no intersects???
Any suggestions, Threejs wizards?

three.js: is it possible to render THREE.Points and THREE.Mesh in the same scene?

I tried to add a Points Object and a Mesh Object into the same scene. But once I add the Mesh the Points disappear. When I remove the Mesh the Points appear again. Is it possible with three.js to have both in the scene at the same time? I'm using r76 now. It worked before with Three.ParticleSystem in threejs r63. Is this a bug or missed I something conceptual between r63 and r76?
Same behaviour seems to be with Three.Line and Three.Points which I can't render together either.
Any ideas about that? Thank you in advance.
Well, I'll bite (you don't have any code) -- what's wrong with
// - - - - points
geometry = new THREE.Geometry();
material = new THREE.PointsMaterial( { size:.1 } );
for (i1=1; i1<=10; i1+=1) {
var x1 = Math.random()*2-1;
var y1 = Math.random()*2-1;
var z1 = Math.random()*2-1;
geometry.vertices.push(new THREE.Vector3(x1,y1,z1));
}
object3d = new THREE.Points(geometry, material);
scene.add(object3d);
// - - - - line
geometry = new THREE.Geometry();
geometry.vertices = [ new THREE.Vector3(-1,1,0), new THREE.Vector3(0,-1,0), new THREE.Vector3(1,1,0) ];
material = new THREE.LineBasicMaterial( { color:0xffffff } );
object3d = new THREE.Line(geometry, material);
scene.add(object3d);
// - - - - sphere
geometry = new THREE.SphereGeometry(.5);
material = new THREE.MeshPhongMaterial( {color:0xffffff} );
mesh = new THREE.Mesh(geometry, material);
mesh.scale.x = 2;
mesh.position.set(0, 1, 0);
scene.add(mesh);

Why doesn't my directional light affect the whole scene?

Please see this fiddle - http://jsfiddle.net/vnr2v6mL/
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);
var geometry = new THREE.BoxGeometry(100, 100, 1);
var material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
var plane = new THREE.Mesh(geometry, material);
scene.add(plane);
camera.position.z = 5;
//scene.add(new THREE.AmbientLight(0xdddddd));
var dl = new THREE.DirectionalLight(0x0000ff, 1.0);
dl.position.set(0, 0, 10);
scene.add(dl);
scene.add( new THREE.DirectionalLightHelper(dl, 2.5) );
function render() {
requestAnimationFrame( render );
renderer.render( scene, camera );
}
render();
$(document).ready(function() {
$(document).bind("mousewheel DOMMouseScroll", function(e) {
var delta = e.type === 'DOMMouseScroll' ? -e.originalEvent.detail : e.originalEvent.wheelDelta;
camera.position.z += delta / 120;
});
});
It is my understanding that the lighting should be infinite and parallel, so why does it only light up a circle in the middle of my scene?
Thanks in advance.
You are using MeshPhongMaterial. What you are seeing is the specular highlight only.
Your light is blue. However, your material is green, so it reflects only green light. Therefore, there is no diffuse light reflected from the material.
The material specular reflectance is, by default, 0x111111. So all colors are reflected specularly. Since your light is blue, you get a blue light reflected specularly. In other words, a blue "hot spot".
Consider using a white light, 0xffffff, and adjust the light intensity.
Fiddle: http://jsfiddle.net/vnr2v6mL/1/
three.js r.70

in three.js, the spotlight is not showing a cone on a plane

I have a very simple example: a spot light pointed at a plane. I am expecting to see a cone of light whose diameter depends on the setting of the spot light angle. I cannot see any cone, the whole plane is illuminated, even for very narrow settings of angle.
Here is my jfiddle: http://jsfiddle.net/blwoodley/WLtL4/1/
I'd love to know the source code that produced this picture from https://github.com/mrdoob/three.js/pull/3291 by West Langley. It obviously is working fine in that case.
So I must be doing something obviously wrong, but I can't figure it out.
Some of the code from the jfiddle, it doesn't get much simpler than this:
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.x = 100;
camera.position.y = 100;
camera.position.z = 200;
camera.lookAt({x: 0,y: 0,z: 0});
scene = new THREE.Scene();
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floorMaterial = new THREE.MeshLambertMaterial({ color: 0x222222, side:THREE.DoubleSide });
floor = new THREE.Mesh(new THREE.PlaneGeometry(2000,2000,10,10), floorMaterial);
floor.rotation.x = Math.PI / 2;
floor.position.y = -40;
scene.add(floor);
var light;
light = new THREE.SpotLight(0x008888);
light.position.set(0, 40, 0);
light.lookAt(floor);
light.angle = Math.PI/4;
light.intensity = 30;
light.distance=0;
scene.add(light);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
This is subtle.
You are using MeshLambertMaterial for the plane. You need to change it to MeshPhongMaterial, so the lighting is rendered properly.
As explained here, for MeshLambertMaterial, the illumination calculation is performed only at each vertex.
For MeshPhongMaterial, the illumination calculation is performed at each texel.
So make these changes
floorGeometry = new THREE.PlaneGeometry( 1000, 1000 ); // no need to tessellate it now
var floorMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } ); // 0x222222 is too dark
light.intensity = 1; // a reasonable value
Updated fiddle: http://jsfiddle.net/WLtL4/5/
three.js r.63
Also try to disable target for testing.
I'm getting really weird behavior from it. Sometimes it makes it not render the light at all, no idea why yet. I'll make a demo of the problem later.

Textures and RingGeometry / CylinderGeometry

UPDATE:
I made jsfiddle example - jsfiddle.net/NEXny/1/
[ignore this - just including a code block so stackoverflow will
let me post the above JSFiddle link. Yeah, seriously.]
I'm having trouble with applying texture to RingGeometry and CylinderGeometry, hope this image will explain my issue.
It is possible to apply texture by one of this ways ?
Currently i'm getting very unexpected results...
You have to modify the geometry vertex UVs to your liking.
Instead, why not just use CircleGeometry for your cylinder end-caps. That is, construct the end-caps yourself?
// cylinder
geometry = new THREE.CylinderGeometry( 192, 192, 40, 64, 1, true ); // open-ended
geometry1 = new THREE.CircleGeometry(192, 64);
// end-cap material
material1 = new THREE.MeshBasicMaterial({
map: textures.circle,
overdraw: 0.5 // for canvas renderer only
});
// cylinder material
material = new THREE.MeshBasicMaterial({
map: textures.line,
overdraw: 0.5 // for canvas renderer only
});
object = new THREE.Object3D();
scene.add(object);
// end-caps
var mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.rotation.x = - Math.PI / 2;
mesh1.position.y = 20
object.add(mesh1);
var mesh2 = new THREE.Mesh(geometry1, material1);
mesh2.rotation.x = Math.PI / 2;
mesh2.position.y = -20
object.add(mesh2);
// cylinder
var mesh = new THREE.Mesh(geometry, material);
object.add(mesh);
fiddle: http://jsfiddle.net/NEXny/2/
three.js r.61

Resources