I have a line in 3d space say A(x1, y1, z1) and B(x2, y2, z2). I want to find a new point between line AB starting from A # distance 5. How can I do that.
About my task, I have a line rendered in browser using threejs and I have to calculate points between a line at some intervals.
Subtract start vector from the end vector, set the length of the result vector, add start vector.
var A = new THREE.Vector3( your_coord_values ); // start
var B = new THREE.Vector3( your_coord_values ); // end
var C = new THREE.Vector3().subVectors(B, A).setLength(5).add(A);
simply add 5 times unit direction vector of the line to the start point:
C = A + 5*(B-A)/|B-A|
Related
I have a Geometry with vertices which is a polyline. But the offset I create is not correct. What I'm currently doing is computing the center of the geometry. And offsetting a value relative to the center. Which is not a correct offset.
My current code:
var size = 10;
var geo = this.mesh.geometry,
center = new THREE.Vector3();
geo.computeBoundingBox();
geo.boundingBox.getCenter(center);
geo.vertices.forEach(function(vertice){
var C = new THREE.Vector3()
C.subVectors( vertice, center ).multiplyScalar( 1 + ( size / C.length() ) ).add( center );
vertice.copy(C);
});
geo.verticesNeedUpdate = true;
So now I have another solution in mind, using the previous and next vertice to calculate a better offset base point. The image below might clarify what I'm trying to achieve. I know vertice a, b and c. But what I don't know is the vertice on the collission of the 2 lines with a 90 deg angle.
This way I calculate a better offset per vertice with a better distancing option. Any way on calculating the purple dot between a and b?
If I understand the situation correctly, you should be able to compute the "purpel vertex" (ie center) using the following code. Note that vertex A, B, C are aquired directly, however you may need to modify that depending on how the vertices are stored:
var size = 10;
var geo = this.mesh.geometry,
center = new THREE.Vector3();
geo.computeBoundingBox();
geo.boundingBox.getCenter(center);
// Aquire the vertices A, B, C between which the purpel vertex will "project
// to"
var A = geo.vertices[0]
var B = geo.vertices[1]
var C = geo.vertices[2]
// Compute vectors between A, B, and C that will be needed to calculate
// purpel vertex. Note that "dirAB" is a unit vector (normalized) which
// means we use it to find "center"
const dirAB = new THREE.Vector3().subVectors(B, A).normalize()
const vecAC = new THREE.Vector3().subVectors(C, A)
// This is the distance along AB that the purpel vertex sits at
const proj = dirAB.dot(vecAC)
// Compute the position of "center" (the purpel vertex) based on "proj"
// distance along the "dirAB" unit vector
center = new THREE.Vector3()
.copy(A)
.addScaledVector(dirAB, proj)
// geo.vertices.forEach(function(vertice){
// var C = new THREE.Vector3()
// C.subVectors( vertice, center )
// .multiplyScalar( 1 + ( size / C.length() ) ).add( center );
// vertice.copy(C);
// });
geo.verticesNeedUpdate = true;
My goal is to make an object controls like a spaceship, what I understand is that I need to use quaternions to achieve this goal. For start I'm trying to make my cube to start rotating to left as I press A key, this is the code for that:
if(controls.pressingA === true)
{
//var pLocal = new THREE.Vector3( 0, 0, -1 );
//var pWorld = pLocal.applyMatrix4( me.matrixWorld );
//var dir = pWorld.sub( me.position ).normalize();
var dir = me.getWorldDirection();
var quaternion = new THREE.Quaternion().setFromAxisAngle( dir, 0.05 );
me.rotation.setFromQuaternion( quaternion );
}
As I understand this code the the me.getWorldDirection() gets the axis that the object is facing, then I create quaternion on the axis that I got before and rotate given object by 0.05 degrees in rad, and finally with the last line of code I just apply to quaternion to my object. The problem I got is that it doesn't increase the rotation, it just sets my object to given rotation, how can I make it increase rotation instead of setting it?
Why don't you use one or combination of:
mesh.rotation.x += 0.05;
mesh.rotation.y += 0.05;
mesh.rotation.z += 0.05;
JSFiddle
If you are setting all of them, you can do this
mesh.rotation.set(9, 7, 3)
Basically I want to set the rotation of an object along the world axis by an arbitrary angle. I'm currently using the rotateAroundWorldAxis function (found in another thread) to try to do that.
function render() {
// update mesh position
rotateAroundWorldAxis(mesh, new THREE.Vector3(1, 0, 0), angle);
renderer.render(scene, camera);
}
function rotateAroundWorldAxis(object, axis, radians) {
rotWorldMatrix = new THREE.Matrix4();
rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
rotWorldMatrix.multiply(object.matrix); // pre-multiply
object.matrix = rotWorldMatrix;
object.rotation.setFromRotationMatrix(object.matrix);
}
The problem is I only want to set the angle (as in rotation.x = angle), not increment it (as in rotation.x += angle). Does anybody know how to adapt the above function (rotateAroundWorldAxis) to allow me to set the angle instead of incrementing it?
jsfiddle here
remove the third line in that function
rotWorldMatrix.multiply(object.matrix); // pre-multiply
This is the line that "adds" the two rotations together.
I'm looking to understand quaternions for three.js, but for all the tutorials, I haven't been able to translate them into the application I need. This is the problem:
Given a sphere centered at (0,0,0), I want to angle an object on the sphere's surface, that acts as the focal point for the camera. This point is to be moved and rotated on the surface with keyboard input.
Setting the focal point into a chosen orbit is easy of course, but maintaining the right rotation perpendicular to the surface escapes me. I know quaternions are neccessary for smooth movement and arbitrary axis rotation, but I don't know where to start.
The second part then is rotating the camera offset with the focal point. The snippet I found for this does not have the desired effect anymore, as the cameraOffset does not inherit the rotation:
var cameraOffset = relativeCameraOffset.clone().applyMatrix4( focalPoint.matrixWorld );
camera.position.copy( focalPoint.position.clone().add(cameraOffset) );
camera.lookAt( focalPoint.position );
Update 1: Tried it with fixed camera on the pole and rotating the planet. But unless I'm missing something important, this fails as well, due to the directions getting skewed completely when going towards the equator. (Left becomes forward). Code in update is:
acceleration.set(0,0,0);
if (keyboard.pressed("w")) acceleration.x = 1 * accelerationSpeed;
if (keyboard.pressed("s")) acceleration.x = -1 * accelerationSpeed;
if (keyboard.pressed("a")) acceleration.z = 1 * accelerationSpeed;
if (keyboard.pressed("d")) acceleration.z = -1 * accelerationSpeed;
if (keyboard.pressed("q")) acceleration.y = 1 * accelerationSpeed;
if (keyboard.pressed("e")) acceleration.y = -1 * accelerationSpeed;
velocity.add(acceleration);
velocity.multiplyScalar(dropOff);
velocity.max(minV);
velocity.min(maxV);
planet.mesh.rotation.x += velocity.x;
planet.mesh.rotation.y += velocity.y;
planet.mesh.rotation.z += velocity.z;
So I'm still open for suggestions.
Finally found the solution from a mixture of matrices and quaternions:
//Setup
var ux = new THREE.Vector3(1,0,0);
var uy = new THREE.Vector3(0,1,0);
var uz = new THREE.Vector3(0,0,1);
var direction = ux.clone();
var m4 = new THREE.Matrix4();
var dq = new THREE.Quaternion(); //direction quad base
var dqq; //final direction quad
var dq2 = new THREE.Quaternion();
dq2.setFromAxisAngle(uz,Math.PI/2); //direction perpendicular rot
//Update
if (velocity.length() < 0.1) return;
if (velocity.x) { focalPoint.translateY( velocity.x ); }
if (velocity.y) { focalPoint.translateX( velocity.y ); }
//create new direction from focalPoint quat, but perpendicular
dqq = dq.clone().multiply(focalPoint.quaternion).multiply(dq2);
velocity.multiplyScalar(dropOff);
//forward direction vector
direction = ux.clone().applyQuaternion(dqq).normalize();
//use Matrix4.lookAt to align focalPoint with the direction
m4.lookAt(focalPoint.position, planet.mesh.position, direction);
focalPoint.quaternion.setFromRotationMatrix(m4);
var cameraOffset = relativeCameraOffset.clone();
cameraOffset.z = cameraDistance;
cameraOffset.applyQuaternion(focalPoint.quaternion);
camera.position = focalPoint.position.clone().add(cameraOffset) ;
//use direction for camera rotation as well
camera.up = direction;
camera.lookAt( focalPoint.position );
This is the hard core of it. It pans (and with some extension rotates) around the planet without the poles being an issue.
I'm not sure to understand your problem.
But for help, I draw a boat on a sphere with the code below.
var geometry = new THREE.ShapeGeometry(shape);
var translation = new THREE.Matrix4().makeTranslation(boat.position.x, boat.position.y, boat.position.z);
var rotationZ = new THREE.Matrix4().makeRotationZ(-THREE.Math.degToRad(boat.cap));
var rotationX = new THREE.Matrix4().makeRotationX(-THREE.Math.degToRad(boat.latitude));
var rotationY = new THREE.Matrix4().makeRotationY(Math.PI / 2 + THREE.Math.degToRad(boat.longitude));
var roationXY = rotationY.multiply(rotationX);
geometry.applyMatrix(rotationZ);
geometry.applyMatrix(roationXY );
geometry.applyMatrix(translation);
First, I apply a rotation on Z to define boat cap
Then, I apply
rotation on Y,X to to set the boat perpendicular to the surface of
the sphere
Finally I apply a translation to put the boat on the
surafce of the sphere
The rotations order is important
I'm not sure if the answer is supposed to be blindingly obvious but it eludes me. I'm doing the 3D Graphics class on Udacity that uses three.js. I'm at a point where I'm required to generate a 3d mesh.
I've got the vertices all generating correctly, but I'm stuck at generating faces for them. I can't think of an obvious way to auto generate faces that don't overlap. I've searched and searched around the web but I can't find any information about it. I'm not sure if it's something stupidly obvious or just not very documented. Here's the code:
function PolygonGeometry(sides) {
var geo = new THREE.Geometry();
// generate vertices
for ( var pt = 0 ; pt < sides; pt++ )
{
// Add 90 degrees so we start at +Y axis, rotate counterclockwise around
var angle = (Math.PI/2) + (pt / sides) * 2 * Math.PI;
var x = Math.cos( angle );
var y = Math.sin( angle );
// YOUR CODE HERE
//Save the vertex location - fill in the code
geo.vertices.push( new THREE.Vector3(x, y, 0) );
}
// YOUR CODE HERE
// Write the code to generate minimum number of faces for the polygon.
// Return the geometry object
return geo;
}
I know the basic formula for the minimum number of faces is n-2. But I just can't think of a way to do this without faces overlapping. I don't want anyone to do my work for me, I want to figure it out myself as much as I can. But is there anyone who can point me in the right direction or give me a formula or something?
You can automate your triangulation
For big polygons it can be quite a job to manually add the faces. You can automate the process of adding faces to the Mesh using the triangulateShape method in THREE.Shape.Utils like this:
var vertices = [your vertices array]
var holes = [];
var triangles, mesh;
var geometry = new THREE.Geometry();
var material = new THREE.MeshBasicMaterial();
geometry.vertices = vertices;
triangles = THREE.Shape.Utils.triangulateShape ( vertices, holes );
for( var i = 0; i < triangles.length; i++ ){
geometry.faces.push( new THREE.Face3( triangles[i][0], triangles[i][1], triangles[i][2] ));
}
mesh = new THREE.Mesh( geometry, material );
Where vertices is your array of vertices and with holes you can define holes in your polygon.
Note: Be careful, if your polygon is self intersecting it will throw an error. Make sure your vertices array is representing a valid (non intersecting) polygon.
Assuming you are generating your vertices in a concave fashion and in a counterclockwise manner then if you have 3 sides (triangle) you connect vertex 0 with 1 with 2. If you have 4 sides (quad) you connect vertex 0 with 1 with 2 (first triangle) and then vertex 0 with 2 with 3. If you have 5 sides (pentagon) you connect vertex 0 with 1 with 2 (first triangle) then vertex 0 with 2 with 3 (second triangle and then vertex 0 with 3 with 4. I think you get the pattern.