Ray does not accurately determine the intersection - three.js

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.

Related

How to remove or hide loaded stl in three.js

How remove of hide loaded.load three.js according to the condition for example id the door condition = 0, if will load the flame.stl and reverse
function checkDoorStatus(isDoorOpen, prevIsDoorOpen){
if ( isDoorOpen == 1)
{
var loader = new THREE.STLLoader();
loader.load( 'model/panic.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xa80306, specular: 0x111111, shininess: 200 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0.145, -0.3, -0.29);
mesh.rotation.set( 0 , 0, Math.PI / 2 );
mesh.scale.set( 0.05, 0.05, 0.05);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
} );
//console.log("Panic 1");
}
else if (isDoorOpen == 0)
{
var loader = new THREE.STLLoader();
loader.load( 'model/flame.stl', function ( geometry ) {
var material = new THREE.MeshPhongMaterial( { color: 0xa80306, specular: 0x111111, shininess: 200 } );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.set( 0.145, -0.3, -0.29);
mesh.rotation.set( 0 , 0, Math.PI / 2 );
mesh.scale.set( 0.05, 0.05, 0.05);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add( mesh );
} );
//console.log("Panic 0");
}
}
According to my understanding, you want to show only one mesh at a time based on some condition. If that is the case, one possible solution is give a name to your mesh before adding to the scene and remove the old door based on its name before adding the new one. For example
mesh.name = "openDoor";
scene.remove(scene.getObjectByName("closedDoor"));
scene.add( mesh )
Hope it helps.

Create Rope in Three.js using Physics from Ammo.js or Cannon.js

I have been trying to create in three.js a rope hanging from a point using any of the 3D physics libraries (ammo.js, cannon.js), but the only one I have successfully done is with (2D)verlet.js.
I really need and want to create it in 3D because I need two ropes attached to a midpoint so that I can show the instability of the midpoint as a load is applied. Something similar as the attached image.
enter image description here
To be honest, I have not idea how to start, I have some experience with Three.js, but non with ammo.js or cannon.js. So far I have been trying to understand the codes for the examples in these links with not success.
http://schteppe.github.io/cannon.js/demos/constraints.html
https://threejs.org/examples/#webgl_physics_rope
I even tried to make a rope using spring function from cannon.js, but you can see that my example is not success.
Can somebody please help me or guide me into the correct way to begin my task?
This is the Code I began to write using Cannon.js:
function initCannon()
{
world = new CANNON.World();
world.gravity.set(.2,-10,.2);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
var mass = 1;
var damping = 1;
// STATIC SPHERE
var sphereShape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
mass = 0;
sphereBody = new CANNON.Body({ mass: 0 });
sphereBody.addShape(sphereShape);
sphereBody.position.set(.5,8,.5);
world.addBody(sphereBody);
// DINAMIC SPHERE 1
var shape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body = new CANNON.Body({ mass: 1 });
body.addShape(shape);
body.angularDamping = damping;
body.position.set(0,8,0);
world.addBody(body);
// DINAMIC SPHERE 2
var shape2 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body2 = new CANNON.Body({ mass: 1 });
body2.addShape(shape2);
body2.angularDamping = damping;
body2.position.set(0,8,0);
world.addBody(body2);
// DINAMIC SPHERE 3
var shape3 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body3 = new CANNON.Body({ mass: 1 });
body3.addShape(shape3);
body3.angularDamping = damping;
body3.position.set(0,8,0);
world.addBody(body3);
var size = 1;
var rebote = 1;
var spring = new CANNON.Spring(body,sphereBody,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring2 = new CANNON.Spring(body2, body,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring3 = new CANNON.Spring(body3, body2,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
world.addEventListener("postStep",function(event){ spring.applyForce(); });
world.addEventListener("postStep",function(event){ spring2.applyForce(); });
world.addEventListener("postStep",function(event){ spring3.applyForce(); });
}
function initThree()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.y = 3;camera.position.z = 15;
scene.add( camera );
controls = new THREE.TrackballControls( camera );
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
var material_wire = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe: true } );
var sphere_size = .8;
var segmentos = 5;
geometry_sphere = new THREE.SphereGeometry( sphere_size, segmentos, segmentos );
sphere = new THREE.Mesh( geometry_sphere, material_wire );
scene.add( sphere );
geometry = new THREE.SphereGeometry( sphere_size, segmentos,segmentos ); // RRT DEFINE TAMANO DE CUBE
mesh = new THREE.Mesh( geometry, material_wire );
scene.add( mesh );
mesh2 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh2 );
mesh3 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh3 );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
updatePhysics();
render();
}
function updatePhysics() {
// Step the physics world
world.step(timeStep);
sphere.position.copy(sphereBody.position);
mesh.position.copy(body.position); // HACE QUE SE VEA
mesh2.position.copy(body2.position);
mesh3.position.copy(body3.position);
}
function render() {
renderer.render( scene, camera );
}

U-shaped magnet geometry in three.js

I want to create a "U" shaped magnet in three.js. So can I use TubeGeometry for that?
So if this is the code for creating a 3D sin curve. How can I make it as "U" shaped Magnet?
var CustomSinCurve = THREE.Curve.create(
function ( scale ) { //custom curve constructor
this.scale = ( scale === undefined ) ? 1 : scale;
},
function ( t ) { //getPoint: t is between 0-1
var tx = t * 3 - 1.5;
var ty = Math.sin( 2 * Math.PI * t );
var tz = 0;
return new THREE.Vector3( tx, ty, tz ).multiplyScalar(this.scale);
}
);
var path = new CustomSinCurve( 10 );
var geometry = new THREE.TubeGeometry( path, 20, 2, 8, false );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
If the shape of the magnet's profile is not critical (rectangle instead of circle), then you can use THREE.ExtrudeGeometry():
var path = new THREE.Shape(); // create a U-shape with its parts
path.moveTo(-1, 1);
path.absarc(0, 0, 1, Math.PI, Math.PI * 2);
path.lineTo(1, 1);
path.lineTo(.8, 1);
path.absarc(0, 0, .8, Math.PI * 2, Math.PI, true);
path.lineTo(-.8,1);
path.lineTo(-1, 1);
var extOpt = { // options of extrusion
curveSegments: 15,
steps: 1,
amount: .2,
bevelEnabled: false
}
var uGeom = new THREE.ExtrudeGeometry(path, extOpt); // create a geometry
uGeom.center(); // center the geometry
var average = new THREE.Vector3(); // this variable for re-use
uGeom.faces.forEach(function(face){
average.addVectors(uGeom.vertices[face.a], uGeom.vertices[face.b]).add(uGeom.vertices[face.c]).divideScalar(3); // find the average vector of a face
face.color.setHex(average.x > 0 ? 0xFF0000 : 0x0000FF); // set color of faces, depends on x-coortinate of the average vector
});
var uMat = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors }); // we'll use face colors
var u = new THREE.Mesh(uGeom, uMat);
scene.add(u);
jsfiddle example

Three.js shadow corresponds to bounding box, not actual model shape

I'm trying to get a correct-looking shadow for a dinosaur model (Three.js JSON format).
The shadow displays, but it's rectangular, as though it thinks the dinosaur model is just a simple cuboid (as screengrabbed below).
How can I generate a shadow that corresponds to the actual shape of the dinosaur?
I've checked in Blender that there's no containing box visible in the OBJ model, from which I created the JSON model file by using the Three.js OBJ to JSON converter.
Here's some snippets of the relevant pieces of code:
/* Dinosaur! */
var loader = new THREE.JSONLoader();
var filePath = 'models/trex/trex.js';
loader.load(filePath, function(geometry, materials) {
mesh = new THREE.Mesh( geometry,
new THREE.MeshFaceMaterial( materials ) );
mesh.scale.set(1000, 1000, 1000);
mesh.position.set( 0, -75, 0 );
mesh.rotation.y = Math.PI;
mesh.castShadow = true;
scene.add( mesh );
});
...
/* Lights */
var ambientLight = new THREE.AmbientLight( 0xFFFFFF );
scene.add( ambientLight );
var directionalLight = new THREE.DirectionalLight( 0xeeeeff, 0.5 );
directionalLight.position.set(0, 0, 1);
scene.add( directionalLight );
var spotlight = new THREE.SpotLight(0xFFFFFF, 0.2, 2000);
spotlight.position.set( 50, 100, 0 );
spotlight.target.position.set( 0, 0, 0 );
spotlight.castShadow = true;
scene.add( spotlight );
...
/* Renderer */
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xffffff);
renderer.setSize(renderWidth, renderHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
container.appendChild(renderer.domElement);
...
/* Terrain */
var img = new Image();
img.onload = function() {
heightData = buildHeightData(img);
var plane = new THREE.PlaneGeometry( 100, 100, HEIGHT_MAP_SIZE-1, HEIGHT_MAP_SIZE-1 );
var l = plane.vertices.length;
for( var i=0; i < l; i++ ) {
// We change z because by default the plane will be placed vertically.
// We rotate it afterwards (so the effect on z will end up being the
// effect on y).
plane.vertices[i].z = heightData[i] * 10;
}
terrainMesh = buildMesh(
{
geometry: plane,
scale: 100,
x: 0,
y: -370,
z: -1050,
material: terrainMaterial
} );
terrainMesh.rotation.x = -Math.PI / 2;
terrainMesh.receiveShadow = true;
scene.add( terrainMesh );
};
img.src = 'img/heightmap.jpg';
p.s. I'm using Three.js v66.
Oops. I had jumped to an incorrect conclusion. It was just because the spotlight was not high enough (see new screengrab, with shadowCameraVisible = true).

Three.js - Cube and sphere clipping strangely with plane

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

Resources