Three.js - Cube and sphere clipping strangely with plane - three.js

I'm having an issue where it looks like the cube and sphere are clipping with the plane. It seems to happen when I move the cube (using the keyboard) toward the back of the scene. It also happens when I use the trackball controls to move around the scene. Sometimes the cube and sphere are visible even when I turn the camera so I am looking at the bottom of the plane.
Some code that might be of use, contains camera variables, creation of plane, sphere, and cube. I have images too: http://imgur.com/0VlZLmP
//CAMERA
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 20000;
//Renderer
ShapeShifter.renderer = new THREE.CanvasRenderer();
//Sphere
var sphereGeometry = new THREE.SphereGeometry( 50, 32, 16 );
var sphereMaterial = new THREE.MeshLambertMaterial( { color: 0x8888FF, overdraw: true } );
ShapeShifter.sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
ShapeShifter.sphere.position.set( 100, 50, -10 );
ShapeShifter.scene.add( ShapeShifter.sphere );
//Cube
var cubeGeometry = new THREE.CubeGeometry( 50, 50, 50 );
var cubeMaterial = new THREE.MeshBasicMaterial( { color: 0xFF4422 } );
ShapeShifter.cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
ShapeShifter.scene.add( ShapeShifter.cube );
ShapeShifter.cube.position.set( -40, 50, 200 );
//Floor
var floorGeometry = new THREE.PlaneGeometry( 1000, 1000 );
var floorMaterial = new THREE.MeshBasicMaterial( { color: 0x4DBD33, overdraw: true } );
ShapeShifter.floor = new THREE.Mesh( floorGeometry, floorMaterial );
ShapeShifter.floor.material.side = THREE.DoubleSide;
ShapeShifter.floor.position.y = 0;
ShapeShifter.floor.rotation.x = Math.PI / 2;
ShapeShifter.scene.add( ShapeShifter.floor );

This is a known limitation of CanvasRenderer.
You can reduce these artifacts by increasing the tessellation of your geometry -- particularly the plane.
var floorGeometry = new THREE.PlaneGeometry( 1000, 1000, 10, 10 ); // will help
var cubeGeometry = new THREE.CubeGeometry( 50, 50, 50, 2, 2, 2 ); // may help

Related

How to animate a threeJS object using GSAP?

I have been learning threeJS just recently and can't get passed a problem. I tried to animate a extruded triangle using the GSAP library. It is just a simple animation to have the triangle move to the right but it seems I did something wrong. Any help is much appreciated.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create Triangles
var material = new THREE.MeshPhongMaterial({
color: 0xf6c12a,
shininess: 70
});
var shape = new THREE.Shape();
shape.moveTo(0, 0);
shape.lineTo(2, 3);
shape.lineTo(4, 0);
shape.lineTo(0, 0);
var extrudeSettings = {
steps: 5,
depth: 1,
bevelEnabled: true,
bevelThickness: 0.3,
bevelSize: 0.5,
bevelOffset: 0,
bevelSegments: 1
};
var geometry = new THREE.ExtrudeBufferGeometry(shape, extrudeSettings);
// Sets the origin to the center of geometry for rotation
geometry.center();
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = 0;
mesh.position.y = 0;
mesh.position.z = -5;
mesh.scale.set(1.5, 1.5, 1.5);
scene.add(mesh);
gsap.to(mesh, { duration: 2, x: 300 });
camera.position.z = 5;
// Background
var geometry = new THREE.PlaneGeometry(1000, 1000, 1);
var material = new THREE.MeshPhysicalMaterial({ color: 0x444444 });
var plane = new THREE.Mesh(geometry, material);
plane.position.z = -50;
scene.add(plane);
// Lighting
var ambientLight = new THREE.AmbientLight(0xffffff, 0.55);
scene.add(ambientLight);
var pointLight1 = new THREE.PointLight(0xf9eac8, 1, 100);
pointLight1.position.set(5, 10, 0);
pointLight1.castShadow = true;
pointLight1.shadow.camera.top = 20;
scene.add(pointLight1);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
Here is the link to Codepen
Tried to put the gsap code into different position but maybe that's not the problem.
gsap.to(mesh.position, { duration: 2, x: 300 });
the value that you want to change is mesh.position.x not mesh.x
just add .position it will work

Connecting two components in Three.js

I would like to build something that allows the connection of two components, kind of like a guitar cable will plug into an amp from a guitar. So I want to connect to one point, and then drag the connection to a second point and have there be some natural hang in the rope. I made this example from a previous SO question (Three.js rope / cable effect - animating thick lines), but I can't seem to get the calculation right. So the question would be, how would I be able to make a function with this signature:
function drawSpline(startPoint, endPoint, ropeLength) {
// returns a new THREE.Line object with a natural curvature for "slack" in the rope between the two points
}
This is what I have so far:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
scene.add(camera);
camera.position.z = 10;
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
const RADIUS = 1;
const SEGMENTS = 16;
const RINGS = 16;
const sphereMaterial =
new THREE.MeshLambertMaterial(
{
color: 0xCC0000
});
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(
RADIUS,
SEGMENTS,
RINGS),
sphereMaterial);
sphere.position.z = 0;
const pointLight =
new THREE.PointLight(0xFFFFFF);
// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
// add to the scene
scene.add(pointLight);
const shiftRatio = 7.5;
scene.add(drawSpline({x: 0, y: -3, z: 0}, {x: 6, y: 1, z: 0}, 'blue'));
function drawSpline(beginning, end, clr){
let ySign = Math.sign((end.y + beginning.y) / 2)
let appliedRatio = shiftRatio;
let midVector = new THREE.Vector3( (end.x + beginning.x) / 8, (end.y+beginning.y)/2, (end.z+beginning.z)/ 2 )
let positionVector = new THREE.Vector3(0,end.y-beginning.y,end.z-beginning.z)
let orthogVector = new THREE.Vector3(0,positionVector.z,-positionVector.y).normalize()
var curve = new THREE.CatmullRomCurve3( [
new THREE.Vector3( beginning.x, beginning.y, beginning.z ),
midVector.clone().addScaledVector(orthogVector,ySign*appliedRatio),
new THREE.Vector3( end.x, end.y, end.z ),
]);
var points = curve.getPoints( 20 );
console.log(points);
var geometry = (new THREE.BufferGeometry()).setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : clr } );
// Create the final object to add to the scene
var curveObject = new THREE.Line( geometry, material );
return curveObject;
}

Ray does not accurately determine the intersection

I want to find point of intersection curve and line. Created raycast, but it doesn't work well. The point of the ray is far from the actual intersection.
Webgl 1, threejs 0.109
var sartPoint = new THREE.Vector3( -30, -50, 0 );
var endPoint = new THREE.Vector3( 50, 80, 0 );
var geometry = new THREE.Geometry();
geometry.vertices.push(sartPoint);
geometry.vertices.push(endPoint);
var materialTmp = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 5 } );
var itemTmp = new THREE.Line( geometry, materialTmp );
_this.add( itemTmp, 'lines' );
scene.updateMatrixWorld()
var curve = new THREE.EllipseCurve(
0, 0, // ax, aY
10, 10, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var points = curve.getPoints( 10 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff00ff } );
var ellipse = new THREE.Line( geometry, material );
scene.add( ellipse );
var raycaster = new THREE.Raycaster(sartPoint, endPoint.clone().normalize());
var intersects = raycaster.intersectObject( ellipse );
console.log(intersects);
if(intersects.length > 0){
// FIRST dot of intersect
var dotGeometry2 = new THREE.Geometry();
dotGeometry2.vertices.push(intersects[0].point);
var dotMaterial2 = new THREE.PointsMaterial( { size: 5, color: 0x00ff00 } );
var dot2 = new THREE.Points( dotGeometry2, dotMaterial2 );
_this.add( dot2, 'points' );
}
The second argument to the Raycaster constructor is a direction vector. Instead of:
endPoint.clone().normalize()
I think you want:
endPoint.clone().sub(startPoint).normalize()
It is work if
curve.getPoints( 10 );
When
curve.getPoints( 100 );
That doesn't work.

three.js transparent sphere glitch

I have a transparent sphere and a spot light and that's about it. My sphere displays visual glitches, like striations.
see: http://jsfiddle.net/blwoodley/tvcogqkg/3/
(Note the grid is not necessary to manifest the bug. I just put it in there to show that transparency is working otherwise fine).
Any thoughts on how to get rid of these glitches? They seem to depend on the relative position of the camera and spot light.
Using three.js, r71.
Here is the code from the fiddle since SO seems to want it:
var SCREEN_WIDTH = window.innerWidth - 100;
var SCREEN_HEIGHT = window.innerHeight - 100;
var camera, scene, _planeMesh;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.set( 380, 80, 100 );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 180, 160, 0 );
var grid = new THREE.GridHelper(400, 40);
grid.position.y = -20;
scene.add(grid);
scene.add(spotLight);
camera.lookAt( scene.position );
var material = new THREE.MeshPhongMaterial( {
color: 0xaaaa00,
emissive: 0xaa0000,
specular: 0xaa00aa,
shininess: 10,
side: THREE.DoubleSide,
shading: THREE.SmoothShading,
opacity: .8, transparent: true } );
var size = 16.0;
var sphereGeo = new THREE.SphereGeometry( size, 32, 16 );
var mesh = new THREE.Mesh( sphereGeo, material);
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.y = 40;
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.x = 60;
scene.add(mesh);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
animate();
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
webglRenderer.render(scene, camera);
}
Remove the attribute side: THREE.DoubleSide. Since you are drawing spheres, you don't need it.

how to have the shadow of a lightshade on surrounding walls in three.js

I have created a scene with a light shade, walls surrounding it, and few light sources. I want the spotlights inside the lamp shade cast shadow on the walls.I played with parameters of the spotlight, but I could not achieve having shadow on the walls. here is my code:
<html>
<head>
<title>Lightshade</title>
<script src="three.js"> </script>
<script src="TrackballControls.js"></script>
</head>
<body>
<script>
//declaring variables
var camera, scene, renderer;
var controls;
var cone, coneGeometry;
scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera( -window.innerWidth / 25, window.innerWidth / 25, window.innerHeight / 25, -window.innerHeight / 25, -10000, 1000000);
camera.position.set( 0, 2.0, 5.0);
camera.lookAt(scene.position);
//adding the renderer to the screen
renderer = new THREE.WebGLRenderer( { antialias: true} );
renderer.setClearColor( 0xeeeeee , 0); //eeeeee
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMapEnabled = true;
document.body.appendChild( renderer.domElement );
//adding the camera interactive method
controls = new THREE.TrackballControls( camera, renderer.domElement );
controls.noKeys = true;
//creating materials for lightshade
BlightshadeMaterial = new THREE.MeshBasicMaterial({color:0xffeb00,wireframe:false, side:THREE.DoubleSide, ambient: 0xffffff});
lightshadeMaterial = new THREE.MeshPhongMaterial({color:0xffeb00,transparent: true,opacity: 0.6,wireframe:false, side:THREE.DoubleSide, ambient: 0xffffff});
// adding some light to the screen
var light3 = new THREE.PointLight( 0xffffff, 1, 100);
light3.position.set( 0, 30.0, 0 );
scene.add( light3 );
var light1 = new THREE.PointLight( 0xffffff,0.7, 100 );
light1.position.set( 0, 4.0, 0 );
scene.add( light1 );
var light2 = new THREE.PointLight( 0xffffff, 0.7, 100 );
light2.position.set( 0, -1.0, 0 );
scene.add( light2 );
var light4 = new THREE.PointLight( 0xffffff, 1, 100);
light4.position.set( 30.0, 16.0, 30.0 );
scene.add( light4 );
var light5 = new THREE.PointLight( 0xffffff, 1, 100);
light5.position.set( -30.0, 16.0, 30.0 );
scene.add( light5 );
coneGeometry = new THREE.CylinderGeometry( 5, 12.5, 15.0, 30, 20 , true);
cone = new THREE.Mesh(coneGeometry,lightshadeMaterial);
cone.castShadow = true;
scene.add(cone);
innerConeGeometry = new THREE.CylinderGeometry( 4.5, 12.0, 15.0, 30,20 , true);
innerCone = new THREE.Mesh(innerConeGeometry,lightshadeMaterial);
innerCone.castShadow = true;
scene.add(innerCone);
upGeometry = new THREE.RingGeometry( 4.5, 5.0, 30 ,3 );
upSide = new THREE.Mesh( upGeometry, BlightshadeMaterial );
scene.add( upSide );
upSide.geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2));
upSide.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0,7.5,0));
downGeometry = new THREE.RingGeometry( 12.0, 12.5, 30 ,3 );
downSide = new THREE.Mesh( downGeometry, BlightshadeMaterial );
scene.add( downSide );
downSide.geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2));
downSide.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0,-7.5,0));
//Creating the shadow
var point = new THREE.Mesh(new THREE.SphereGeometry(0.2), new THREE.MeshBasicMaterial( {color: 0xffff00 } ));
point.position.set(0,2.5,-1.0);
scene.add( point );
var spotlight = new THREE.SpotLight(0xffffff ,3, 800 , Math.PI/4);
spotlight.target = point;
//to cast the light horizontally to the light shade
spotlight.position.set(0,2.5,0);
spotlight.shadowCameraVisible = true;
spotlight.shadowDarkness = 0.95;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
spotlight.shadowMapWidth = 512;
spotlight.shadowMapHeight = 512;
spotlight.shadowCameraFov = 300;
scene.add(spotlight);
var point = new THREE.Mesh(new THREE.SphereGeometry(0.2), new THREE.MeshBasicMaterial( {color: 0xffff00} ));
point.position.set(1.0,2.5,0);
scene.add( point );
var spotlight = new THREE.SpotLight(0xffffff ,3, 800, Math.PI/4);
spotlight.target = point;
//to cast the light horizontally to the light shade
spotlight.position.set(0,2.5,0);
spotlight.shadowDarkness = 0.95;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
spotlight.shadowMapWidth = 512;
spotlight.shadowMapHeight = 512;
spotlight.shadowCameraFov = 30.0;
scene.add(spotlight);
var point = new THREE.Mesh(new THREE.SphereGeometry(0.2), new THREE.MeshBasicMaterial( {color: 0xffff00} ));
point.position.set(-1.0,2.5,0);
scene.add( point );
var spotlight = new THREE.SpotLight(0xffffff ,3, 800, Math.PI/4);
spotlight.target = point;
//to cast the light horizontally to the light shade
spotlight.position.set(0,2.5,0);
spotlight.shadowDarkness = 0.95;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
spotlight.shadowMapWidth = 512;
spotlight.shadowMapHeight = 512;
spotlight.shadowCameraFov = 30.0;
scene.add(spotlight);
var point = new THREE.Mesh(new THREE.SphereGeometry(0.2), new THREE.MeshBasicMaterial( {color: 0xffff00} ));
point.position.set(1.0,2.5,-1.0);
scene.add( point );
var spotlight = new THREE.SpotLight(0xffffff ,3, 800, Math.PI/4);
spotlight.target = point;
//to cast the light horizontally to the light shade
spotlight.position.set(0,2.5,0);
spotlight.shadowDarkness = 0.95;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
spotlight.shadowMapWidth = 512;
spotlight.shadowMapHeight = 512;
spotlight.shadowCameraFov = 300;
scene.add(spotlight);
var point = new THREE.Mesh(new THREE.SphereGeometry(0.2), new THREE.MeshBasicMaterial( {color: 0xffff00} ));
point.position.set(-1.0,2.5,-1.0);
scene.add( point );
var spotlight = new THREE.SpotLight(0xffffff ,3, 800, Math.PI/4);
spotlight.target = point;
//to cast the light horizontally to the light shade
spotlight.position.set(0,2.5,0);
spotlight.shadowDarkness = 0.95;
// must enable shadow casting ability for the light
spotlight.castShadow = true;
spotlight.shadowMapWidth = 512;
spotlight.shadowMapHeight = 512;
spotlight.shadowCameraFov = 30.0;
scene.add(spotlight);
//create walls and floor
var floorMaterial = new THREE.MeshPhongMaterial({side: THREE.DoubleSide} );
var floorGeometry = new THREE.PlaneBufferGeometry(170, 170, 100, 100);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -Math.PI / 2;
floor.position.y = -70;
// Note the mesh is flagged to receive shadows
floor.castShadow= false;
floor.receiveShadow = true;
scene.add(floor);
//front wall
var frontMaterial = new THREE.MeshPhongMaterial( {side: THREE.DoubleSide } );
var frontGeometry = new THREE.PlaneBufferGeometry(170, 100, 100, 100);
var front = new THREE.Mesh(frontGeometry, frontMaterial);
front.position.z = -85;
front.position.y = -20;
//front.rotation.x = Math.PI / 2;
// Note the mesh is flagged to receive shadows
front.castShadow= false;
front.receiveShadow = true;
scene.add(front);
//right wall
var rightMaterial = new THREE.MeshPhongMaterial( {side: THREE.DoubleSide} );
var rightGeometry = new THREE.PlaneBufferGeometry(170, 100, 100, 100);
var right = new THREE.Mesh(rightGeometry, rightMaterial);
right.rotation.y = Math.PI / 2;
right.position.x = 85;
right.position.y = -20;
// Note the mesh is flagged to receive shadows
right.castShadow= false;
right.receiveShadow = true;
scene.add(right);
//left wall
var leftMaterial = new THREE.MeshPhongMaterial( {side: THREE.DoubleSide} );
var leftGeometry = new THREE.PlaneBufferGeometry(170, 100, 100, 100);
var left = new THREE.Mesh(leftGeometry, leftMaterial);
left.rotation.y = Math.PI / 2;
left.position.x = -85;
left.position.y = -20;
// Note the mesh is flagged to receive shadows
left.castShadow= false;
left.receiveShadow = true;
scene.add(left);
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
controls.update();
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
Alternatively, do you know any other better way to have the shadow of the light shade on the walls. Thank you in advance.
This seems similar to an issue I had: Three.js DoubleSided material doesn't cast shadow on both sides of planar parametric geometry
In particular, "The material.side property is not taken into consideration when casting shadows."

Resources