Moving the camera in the direction it's facing, with ThreeJS - javascript

Say I have a camera placed at:
{
x: 10,
y: 30,
z: 20
}
It's rotation is:
{
x: 0.1,
y: 0.2,
z: 0.3
}
I want to move the camera 1 unit from it's current position in the direction it's facing.
How do I do calculate the cameras new position?
I'm using ThreeJS.

The THREE.Camera class extends the THREE.Object3D class.
You can get the camera direction with the getWorldDirection method from the base class:
It returns a vector representing the direction in which the camera is looking, in world space.
When you have this direction vector you can use it to move the camera in the desired direction:
var direction = new THREE.Vector3();
camera.getWorldDirection( direction );
To move only 1 in that direction you can simply do:
camera.position.add( direction );
If you want to move more you could for example use the multiplyScalar method from the THREE.Vector3 class and multiply with the desired distance.
distance = 10;
camera.position.add( direction.multiplyScalar(distance) );

The camera looks down its local negative-z axis. So to move the camera in the direction it is facing, use this method:
camera.translateZ( - distance );
This is the most-efficient method.
three.js r.78

Related

How to move the camera with the camera angle?

I made a simple threeJS 3d app in which you can look around and move with 4 keys. The problem is that it moves in the same direction no matter where you look to, obviously because I use:
camera.position.x += 0.1
You have to set the default displacement of (0.1, 0, 0) to a Vector3, then apply the camera's rotation (its quaternion) to that vector before adding it to its position. See the code below:
// Create camera
var camera = new THREE.PerspectiveCamera();
// Create displacement vector to re-use
var dispVector = new THREE.Vector3();
function onRightKey() {
dispVector.set(0.1, 0, 0); // Right key moves 0.1 on x axis
applyDisplacement();
}
function applyDisplacement() {
// We apply the camera's rotation to the displacement vector
dispVector.applyQuaternion(camera.quaternion);
// Move the camera position by the resulting displacement vector
camera.position.add(dispVector);
}
You can apply this same idea to the other keys: (-0.1, 0, 0) if you want to move left, or (0, 0.1, 0) if you want to move up, etc:
function onLeftKey() {
dispVector.set(-0.1, 0, 0); // Left key moves -0.1 on x axis
applyDisplacement();
}
function onUpKey() {
dispVector.set(0, 0.1, 0); // Left key moves 0.1 on y axis
applyDisplacement();
}

How to rotate a ThreeJS Object3D object around its end?

Is it possible to rotate an Object3D object about its end? I found my object's center with const boundingBox = new THREE.Box3().setFromObject(this.object) to determine the center. Would rotating at a point mean translating the object to one point, rotate, then translate back?
Is it possible to rotate an Object3D object about its end?
Yes. By default, Object3D rotates about its center, but it's possible to change rotation point by "wrapping" object in parent (Object3D) and setting position for parent (this will be also a rotation point):
function changeRotationPoint(obj, scene, position) {
// create parent and add it to scene
const parent = new THREE.Object3D();
parent.add(obj);
if (obj.parent) {
obj.parent.add(parent);
} else {
// add to THREE scene if obj doesn't have a
// parent
scene.add(parent);
}
// position for rotation,
// for example (put your data): { x: 0.1, y: 0.1, z: 0 }
parent.position.set(position.x, position.y, position.z);
// correct position of obj, so only rotation point
// will be changed
const x = obj.position.x - position.x,
const y = obj.position.y - position.y,
const z = obj.position.z - position.z
obj.position.set(x, y, z);
}
// call function
changeRotationPoint(this.object, scene, { x: 0.1, y: 0.1, z: 0 });
// rotate this.object
this.object.parent.rotation.set(0.1, 0.2, 0.3);

Three.js: Rotate Cylinder into Vector3 direction

I've already searched, but didn't find anything that helps:
I got an vector and a CylinderGeometry Mesh. I want to acchieve, that the cylinder is facing the point where the vector is showing. As input I got a position (c) and a direction (m) (like a line equation: y = mx + c):
function draw (m,c, _color) {
//... create the geometry and mesh
// set the position
line.position.x = c.x;
line.position.y = c.y;
line.position.z = c.z;
// i've tried something like this:
line.lookAt(c.add(m));
//.. and add to scene
}
But it looks like the direction is the direct opposite of what I want to acchieve.
I've also tried stuff like translation:
geometry.applyMatrix( new THREE.Matrix4().makeTranslation(0, length/2, 0));
and tried to get the rotation manually like line.rotation.x = direction.angleTo(vec3(1,0,0))* 180 / Math.PI;. But none of them worked like I needed.
This works for me:
// Make the geometry (of "distance" length)
var geometry = new THREE.CylinderGeometry( 0.6, 0.6, distance, 8, 1, true );
// shift it so one end rests on the origin
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, distance / 2, 0 ) );
// rotate it the right way for lookAt to work
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( THREE.Math.degToRad( 90 ) ) );
// Make a mesh with the geometry
var mesh = new THREE.Mesh( geometry, material );
// Position it where we want
mesh.position.copy( from.sceneObject.position );
// And make it point to where we want
mesh.lookAt( to.sceneObject.position );

Three.js cylinder rotation in 3d plane

Ive been having the linewidth problem (something to do with ANGLE on window). I have resorted to using cylinders between 2 points (in 3D space). I have already solved the issue on getting the length of the cylinder based on the 2 points-3D distance formula.
I have been having trouble however getting the angle. I want the cylinder to rotate so that the angle found will make it so that the cylinder connects the two points.
Essensially I am trying to find a way to find the angle between (x1,y1,z1) and (x2,y2,z2). And having it modify a cylinder (cylinder.rotation.x, cylinder.rotation.y, and cylinder.rotation.z).
You can use a transformation matrix to do that. Here's some example code:
function createCylinderFromEnds( material, radiusTop, radiusBottom, top, bottom, segmentsWidth, openEnded)
{
// defaults
segmentsWidth = (segmentsWidth === undefined) ? 32 : segmentsWidth;
openEnded = (openEnded === undefined) ? false : openEnded;
// Dummy settings, replace with proper code:
var length = 100;
var cylAxis = new THREE.Vector3(100,100,-100);
var center = new THREE.Vector3(-100,100,100);
////////////////////
var cylGeom = new THREE.CylinderGeometry( radiusTop, radiusBottom, length, segmentsWidth, 1, openEnded );
var cyl = new THREE.Mesh( cylGeom, material );
// pass in the cylinder itself, its desired axis, and the place to move the center.
makeLengthAngleAxisTransform( cyl, cylAxis, center );
return cyl;
}
// Transform cylinder to align with given axis and then move to center
function makeLengthAngleAxisTransform( cyl, cylAxis, center )
{
cyl.matrixAutoUpdate = false;
// From left to right using frames: translate, then rotate; TR.
// So translate is first.
cyl.matrix.makeTranslation( center.x, center.y, center.z );
// take cross product of cylAxis and up vector to get axis of rotation
var yAxis = new THREE.Vector3(0,1,0);
// Needed later for dot product, just do it now;
// a little lazy, should really copy it to a local Vector3.
cylAxis.normalize();
var rotationAxis = new THREE.Vector3();
rotationAxis.crossVectors( cylAxis, yAxis );
if ( rotationAxis.length() < 0.000001 )
{
// Special case: if rotationAxis is just about zero, set to X axis,
// so that the angle can be given as 0 or PI. This works ONLY
// because we know one of the two axes is +Y.
rotationAxis.set( 1, 0, 0 );
}
rotationAxis.normalize();
// take dot product of cylAxis and up vector to get cosine of angle of rotation
var theta = -Math.acos( cylAxis.dot( yAxis ) );
//cyl.matrix.makeRotationAxis( rotationAxis, theta );
var rotMatrix = new THREE.Matrix4();
rotMatrix.makeRotationAxis( rotationAxis, theta );
cyl.matrix.multiply( rotMatrix );
}
I didn't write this. Find the full working sample here.
It's part of Chapter 5: Matrices from this awesome free Interactive 3D Graphics course taught using three.js.
I warmly recommend it. If you didn't have a chance to play with transformations you might want to start with Chapter 4.
As a side note. You can also cheat a bit and use Matrix4's lookAt() to solve the rotation, offset the translation so the pivot is at the tip of the cylinder, then apply the matrix to the cylinder.

Rotation anchor point in Three.js

I am defining a cone that I need to be able to rotate around its top point (the point where the cone thickness is the smallest one). I couldn't find yet the way to set the point around which the rotation to happen.
var coneGeometry = new THREE.CylinderGeometry(1000, 0, width, 50, 50, false);
var cone = new THREE.Mesh(coneGeometry, material);
cone.position.x = x;
cone.position.y = y + width / 2;
cone.position.z = z;
// I want this rotation to happen around the point given by the (x, y, z) location
cone.rotation.x = dip;
The cone geometry is centered at the origin. What you need to do is translate the cone geometry right after it is created so the tip of the cone is at the origin.
coneGeometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, coneHeight/2, 0 ) );
(The sign of the translation changes depending on which end of the cone is the small end.)
Now, when you rotate the cone, it will rotate around the tip. The tip will also be located at the position you set.
EDIT: You can now do this, instead:
coneGeometry.translate( 0, coneHeight/2, 0 ); // three.js r.72

Categories

Resources