I am using a raycaster for a projection of a point onto a face. But somehow that doesn't seem to work. I.e. taking point (25,25,300) and direction (0,0,-1) the raycaster doesn't find and intersect with a box of size (30,30,30) located at (0,0,0). Am I doing sth wrong?
var geometry = new THREE.BoxGeometry(30, 30, 30);
var material = new THREE.MeshBasicMaterial( );
var mesh = new THREE.Mesh(geometry, material);
var dir = new THREE.Vector3(0,0,-1);
var p = new THREE.Vector3(25,25,300);
var raycaster = new THREE.Raycaster(p, dir);
var intersects = raycaster.intersectObjects(mesh); // returns an empty array
There are two problems with your example, first is that you are using the method raycaster.intersectObjects which takes an array as argument, when you should be using raycaster.intersectObject which takes an object.
Secondly, you are missing the mesh.
Try these values: var p = new THREE.Vector3(15,15,300); instead. The image below illustrates the problem..
Related
A cube is in the scene. I put a small sphere-geometry objects[i] on the front face. Rotating the cube in a position which hides the front-face. The sphere-geometry is hidden yet too. now I set a ray from the camera to the sphere-geometry but no cube-faces and no sphere-geometry getting intersected. why?
the vectors of the ray origin (camera) and ray direction (objects[i].position) in the console are correctly.
function detectIntersections () {
var detectDirection = new THREE.Vector3();
detectDirection.x = objects[i].position.x;
detectDirection.y = objects[i].position.y;
detectDirection.z = objects[i].position.z;
var detectOrigin = new THREE.Vector3(camera.position.x,camera.position.y,camera.position.z);
var raycaster = new THREE.Raycaster();
raycaster.set(detectOrigin, detectDirection);
var intersects = raycaster.intersectObjects( scene.children, true )};
I expect a non empty intersects-Array.
I have array of XY coordinates from which i have to get the respective Z positions. I have created the following code to achieve same.
This function loops through array and calls further function to get the Z value.
function generate_section(){
for(var i=0;i<points.length;i++){
//temporary try to get for the same.
var pts = points[i];
var z = sectioncall(pts.x,pts.y);
console.log(pts,z);
}
}
The following function is a raycaster which cast the ray for the provided x& y value and cast a downward ray.
function sectioncall(x,y){ //grabs the Z value for the provided XY
var top = new THREE.Vector3(x, y , 30 );
var bottom = new THREE.Vector3(x , y , -30 );
var direction = new THREE.Vector3();
direction = direction.subVectors( bottom, top ).normalize();
//start raycaster
var raycaster = new THREE.Raycaster();
raycaster.set( top, direction );
// calculate objects intersecting the picking ray
var intersects = rayCaster.intersectObjects(scene.getObjectByName('MyObj_s').children);
var rpt = intersects[0].point;
//draw a line the way ray caster casting the ray
var geometry = new THREE.Geometry();
geometry.vertices.push( top );
geometry.vertices.push( rpt );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
var line = new THREE.Line( geometry, material );
scene.add( line );
return rpt;
}
With the above code i get the result like this:
but what i want to achive is the result like this:
So that the returning values will be about for respective XY instead of last XY as you see on the console.
You have slightly made a mistake in the code.
it should be
var intersects = raycaster.intersectObjects(scene.getObjectByName('MyObj_s').children);
you misspelled it as rayCaster.
In my Three.js project i have a mesh using a buffergeometry.
Using raycaster i find the intersection of a ray with this mesh in a specific face of which it says me the index.
How can i find vertices position of this face?
Instead of using the faceIndex, it's easier to use the face property of an intersection object. You can use it like so:
var vA = new THREE.Vector3();
var vB = new THREE.Vector3();
var vC = new THREE.Vector3();
var face = intersection.face;
var geometry = intersection.object.geometry;
var position = geometry.attributes.position;
vA.fromBufferAttribute( position, face.a );
vB.fromBufferAttribute( position, face.b );
vC.fromBufferAttribute( position, face.c );
If you need the vertices in world space, then multiple these three vectors with the world matrix of your object.
three.js R102
It's tough to find an updated answer to this question. Seems like a lot of solutions are using MeshFaceMaterial which is long gone from three.js (around version 53, currently on 84)
From the research I've done, it seems like it's a better strategy to create a Box, turn it into a Sphere and then do the mappings.
Here's what I've got:
I have textures loaded at vars t1 and t2
var geometry = new THREE.BoxGeometry(1,1,1);
for (var i in geometry.vertices) {
var vertex = geometry.vertices[i];
vertex.normalize().multiplyScalar(1);
}
var mat1 = new THREE.MeshLambertMaterial({ map: t1 });
var mat2 = new THREE.MeshLambertMaterial({ map: t2 });
var materials = [mat1, mat2];
var mats = new THREE.MultiMaterial(materials);
var cube = new THREE.Mesh(geometry, mats);
scene.add(cube);
Problems:
This is resulting in Uncaught TypeError: Cannot read property 'visible' of undefined in my console
For shading reasons, I'd like to use a MeshPhongMaterial instead of a MeshLambertMaterial
Any tips would be hugely appreciated!
Take a look at the materialIndex value inside the faces of the geometry. These values are indexes into your materials array.
In your example you will see they have values from 0 to 5 (corresponding to sides of the box), but since only two materials are provided then you'll see an error.
To solve your problem you can just change the materialIndex values on the geometry faces so that they just reference your two materials.
For example:
for (var i = 0; i < geometry.faces.length; i += 1) {
var face = geometry.faces[i];
face.materialIndex = face.materialIndex % 2;
}
In three.js, I'm using PointerLock controls the make a basic first person shooter.
I use
function onDocumentMouseDown( event ) {
var raycaster = new THREE.Raycaster();
mouse3D.normalize();
controls.getDirection( mouse3D );
raycaster.set( controls.getObject().position, mouse3D );
var intersects = raycaster.intersectObjects( objects );
...
}
to detect a collision with an object, which means you "shot" the object.
Now, I want to visualize the path the bullet took. I was thinking about drawing a line from where the user is looking to, in direction of the raycaster, but I can't figure out how to do this... Anyone who can help me? I'm new to three.js, never thought drawing a line would be this hard.
Update:
I'm trying to draw a line using:
var geometry = new THREE.Geometry();
geometry.vertices.push(...);
geometry.vertices.push(...);
var line = new THREE.Line(geometry, material);
scene.add(line);
but I can't figure out what to put in place of the "..." . How can I detect which point the line should go to? And how to determine which point it starts from? The player is able to move and even jump so the starting point is always different too.
You can use the following (using r83):
// Draw a line from pointA in the given direction at distance 100
var pointA = new THREE.Vector3( 0, 0, 0 );
var direction = new THREE.Vector3( 10, 0, 0 );
direction.normalize();
var distance = 100; // at what distance to determine pointB
var pointB = new THREE.Vector3();
pointB.addVectors ( pointA, direction.multiplyScalar( distance ) );
var geometry = new THREE.Geometry();
geometry.vertices.push( pointA );
geometry.vertices.push( pointB );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
var line = new THREE.Line( geometry, material );
scene.add( line );
Codepen at: https://codepen.io/anon/pen/evNqGy
You can use something like this:
function animate_Line(frame, totalFrames) {
//Calculate how much of the line should be drawn every iteration
var delta = lineDistance/(totalFrames);
var deltaSpeed = delta * frame;
for(var i=0; i<f_Ray_List[0].length; i++) {
for(var j=0; j<f_Ray_List[1].length; j++) {
//Change Offsets
line.geometry.vertices[1].y = line.geometry.vertices[0].y - deltaSpeed;
//Update Rays = true (Make FRT rays draw-able)
line.geometry.verticesNeedUpdate = true;
}
}
}
where frame is the current frame (a counter in your animate function), totalFrames would be the amount of frames that the line would take to be animated. The lineDistance can be calculated by using this:
lineDistance = line.geometry.vertices[0].y - line.vertices[1].y; //Add this line where you create the line object.
and remember to call line.geometry.verticesNeedUpdate = true; in every line individually, so that the line would able to be animated.
Notice that this is only based on Line.y axis. This would not be great at first. I'm currently working on converting this to Polar coordinates instead but I have no idea what is going on hahah.