Three.JS: Get position along direction vector - three.js

I have a position vector:
var startPos = new THREE.Vector3(1.2, -2.34, 0.5);
A direction vector:
var direction = new THREE.Vector3(0.657873735, -0.2497291683, 0.71051916);
And a distance:
var distance = 1;
How to calculate a new position vector, starting from startPos that is moved the distance along the direction?

var startPos = new THREE.Vector3(1.2, -2.34, 0.5);
var direction = new THREE.Vector3(0.6578737359955765, -0.24972916834682138, 0.710519166466616);
var distance = 1;
var newPos = new THREE.Vector3();
newPos.addVectors ( startPos, direction.multiplyScalar( distance ) );

Related

Raycaster Set getting Z value for respective XY

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.

How fill a loaded STL mesh ( NOT SIMPLE SHAPES LIKE CUBE ETC) with random particles and animate with this geometry bound in three.js

How I can fill a loaded STL mesh ( like suzane NOT SIMPLE SHAPES LIKE CUBE etc) with random particles and animate it inside this geometry bounds with three.js ?
I see many examples but all of it for simple shapes with geometrical bounds like cube or sphere with limit by coordinates around center
https://threejs.org/examples/?q=points#webgl_custom_attributes_points3
TNX
A concept, using a ray, that counts intersections of the ray with faces of a mesh, and if the number is odd, it means that the point is inside of the mesh:
Codepen
function fillWithPoints(geometry, count) {
var ray = new THREE.Ray()
var size = new THREE.Vector3();
geometry.computeBoundingBox();
let bbox = geometry.boundingBox;
let points = [];
var dir = new THREE.Vector3(1, 1, 1).normalize();
for (let i = 0; i < count; i++) {
let p = setRandomVector(bbox.min, bbox.max);
points.push(p);
}
function setRandomVector(min, max){
let v = new THREE.Vector3(
THREE.Math.randFloat(min.x, max.x),
THREE.Math.randFloat(min.y, max.y),
THREE.Math.randFloat(min.z, max.z)
);
if (!isInside(v)){return setRandomVector(min, max);}
return v;
}
function isInside(v){
ray.set(v, dir);
let counter = 0;
let pos = geometry.attributes.position;
let faces = pos.count / 3;
let vA = new THREE.Vector3(), vB = new THREE.Vector3(), vC = new THREE.Vector3();
for(let i = 0; i < faces; i++){
vA.fromBufferAttribute(pos, i * 3 + 0);
vB.fromBufferAttribute(pos, i * 3 + 1);
vC.fromBufferAttribute(pos, i * 3 + 2);
if (ray.intersectTriangle(vA, vB, vC)) counter++;
}
return counter % 2 == 1;
}
return new THREE.BufferGeometry().setFromPoints(points);
}
The concepts from the previous answer is very good, but it has some performance limitations:
the whole geometry is tested with every ray
the recursion on points outside can lead to stack overflow
Moreover, it's incompatible with indexed geometry.
It can be improved by creating a spatial hashmap storing the geometry triangles and limiting the intersection test to only some part of the mesh.
Demonstration

Draw line in direction of raycaster in three.js

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.

How to rotate an object to make it face a certain direction?

If I know what direction an object is facing for example (0, 0, 1). What is the easiest way to rotate the object to face a direction vector of (1, 1, 1)?
Edit:
I've tried this, but something is wrong with this logic:
var newDir = new THREE.Vector3(1,1,1);
var objectDir= new THREE.Vector3(0, 0, 1);
objectDir.applyQuaternion(object.quaternion); // rotate this vector to object's facing direction
var pos = new THREE.Vector3();
pos.addVectors(newDir, object.position);
var axis = objectDir.cross(newDir).normalize();
var angle = objectDir.angleTo(pos);
object.rotateOnAxis(axis, angle);
Solved it with lookAt:
var newDir = new THREE.Vector3(1, 1, 1);
var pos = new THREE.Vector3();
pos.addVectors(newDir, object.position);
object.lookAt(pos);

three.js - two points, one cylinder, align issue

(new to stackoverflow, new to webgl/three.js, ...)
I'm using three.js r54 to plot a force-directed graph. the edges between the nodes are THREE.Lines, which is fine, but lines are not selectable with a raycaster. so my aim is to take cylinders instead(/along with) of lines(also because I can do some further stuff: using textures,...)
this is what I'm doing to place the cylinders:
// init reference vector
var upVec = new THREE.Vector3(0,1,0);
//---withhin a loop---
// get direction
var direction = startPoint.subSelf(endPoint).clone();
// half length for cylinder height
var halfLength = direction.length() * 0.5;
// get offset
var offset = endPoint.clone().addSelf(direction.clone().multiplyScalar(0.5));
// normalize direc
direction.normalize();
//newUpVec = upVec - (upVec *(dot) direction) * direction - projection of direction
var newUpVec = upVec.clone().subSelf(direction.clone().multiplyScalar(upVec.dot(direction.clone()))).normalize();
var right = newUpVec.clone().crossSelf(direction.clone());
//build rotation matrix
var rot = new THREE.Matrix4(right.x, right.y, right.z, 0,
newUpVec.x, newUpVec.y, newUpVec.z, 0,
direction.x, direction.y, direction.z,0,
0,0,0,1);
//build translation matrix
var transla = new THREE.Matrix4(1, 0, 0, offset.x,
0, 1, 0, offset.y,
0, 0, 1, offset.z,
0, 0, 0, 1);
//build transformation matrix
var transfo = new THREE.Matrix4().multiply(transla, rot);
// create geometry
var cylgeo = new THREE.CylinderGeometry(2, 2, halfLength * 2, 12, 1, false);
cylgeo.applyMatrix(transfo);
var cylMesh = new THREE.Mesh(cylgeo, new THREE.MeshLambertMaterial({color:0x000000,
wireframe: true, shading: THREE.FlatShading}));
(descripted in: http://www.fastgraph.com/makegames/3drotation/ )
So the cylinders are placed at the right offset and align in some kind of way, but not to the two points (start, end) of the edges.
any suggestion would be appreciated!
using that :
object3d-rotation-to-align-to-a-vector
given 2 Vector3 and a scene:
function drawCylinder(vstart, vend,scene){
var HALF_PI = +Math.PI * .5;
var distance = vstart.distanceTo(vend);
var position = vend.clone().addSelf(vstart).divideScalar(2);
var material = new THREE.MeshLambertMaterial({color:0x0000ff});
var cylinder = new THREE.CylinderGeometry(10,10,distance,10,10,false);
var orientation = new THREE.Matrix4();//a new orientation matrix to offset pivot
var offsetRotation = new THREE.Matrix4();//a matrix to fix pivot rotation
var offsetPosition = new THREE.Matrix4();//a matrix to fix pivot position
orientation.lookAt(vstart,vend,new THREE.Vector3(0,1,0));//look at destination
offsetRotation.rotateX(HALF_PI);//rotate 90 degs on X
orientation.multiplySelf(offsetRotation);//combine orientation with rotation transformations
cylinder.applyMatrix(orientation)
var mesh = new THREE.Mesh(cylinder,material);
mesh.position=position;
scene.add(mesh);
}
r58+ code :
function drawCylinder(vstart, vend,scene){
var HALF_PI = Math.PI * .5;
var distance = vstart.distanceTo(vend);
var position = vend.clone().add(vstart).divideScalar(2);
var material = new THREE.MeshLambertMaterial({color:0x0000ff});
var cylinder = new THREE.CylinderGeometry(10,10,distance,10,10,false);
var orientation = new THREE.Matrix4();//a new orientation matrix to offset pivot
var offsetRotation = new THREE.Matrix4();//a matrix to fix pivot rotation
var offsetPosition = new THREE.Matrix4();//a matrix to fix pivot position
orientation.lookAt(vstart,vend,new THREE.Vector3(0,1,0));//look at destination
offsetRotation.makeRotationX(HALF_PI);//rotate 90 degs on X
orientation.multiply(offsetRotation);//combine orientation with rotation transformations
cylinder.applyMatrix(orientation)
var mesh = new THREE.Mesh(cylinder,material);
mesh.position=position;
scene.add(mesh);
}
#jdregister's answer didn't quite work for me in R77, since the cylinder ended up with its center at vstart (rotation and lookAt were otherwise fine).
This modification to the second last line of the R58+ answer did the trick:
mesh.position.set(position.x, position.y, position.z);
There's a very succinct answer here: https://stackoverflow.com/a/44346439/1556416
I paraphrased it here:
function drawCylinder(vstart, vend, radius){
var cylLength = new THREE.Vector3().subVectors(vend, vstart).length();
var cylGeom = new THREE.CylinderGeometry(radius, radius, cylLength, 16);
cylGeom.translate(0, cylLength / 2, 0);
cylGeom.rotateX(Math.PI / 2);
var material = new THREE.MeshLambertMaterial({color: "blue"})
var cyl = new THREE.Mesh(cylGeom, material);
cyl.position.copy(vstart);
cyl.lookAt(vend); // and do the trick with orienation
return cyl
}
In R87 the "vend.clone().add(vstart).divideScalar(2);" is not working
You can position the item like this
mesh.position.copy(start);
mesh.position.lerp(end, 0.5);
All the others from R58 are fine :)

Resources