Three.js Camera Quaternion offset for gyro input - three.js

I'm using deviceorientationcontroller.js for three.js whch uses quaternions for camera orientation. When a user touches the device it overrides the gyro input and uses touch input instead. When the user releases the touch it snaps back to the absolute gyro input quaternion as opposed to offsetting the gyro to accommodate the new camera orientation.
I need to take an initial quaternion value from the camera orientation and offset the gyro input to reflect this starting position.

Related

Can I convert camera rotation to sphere mesh rotation?

I have a very large SphereBufferGeometry that I project an equirectangular 360 image onto in order to create a 360 scene. I have two functions to my application: 1.) to set the initial view of which part of the scene should be viewed at scene load and 2.) to always load the scene at that saved coordinates.
To set the initial view of which part of the scene should be viewed at scene load:
I can use OrbitControls to move the camera to look at a certain direction of this sphere, and I can save the position of the camera when I look at a 360 scene position I like.
To always load the scene at that saved coordinates:
I can set the position of the camera to this previously saved position and view the scene at my favorite starting location.
This works well, but I do not want to set camera position each time a 360 scene loads. Rather, my requirement is to load the scene with camera in a neutral position, and rather the sphere mesh is rotated on the sphere such that I am looking at the [x,y,z] position of my favorite position set earlier.
Is it at all possible to take a camera position and rotation and use those values to rotate or position a mesh on my sphere?
Can I use OrbitControls to rotate the entire scene/sphere instead of the camera onClick?

ThreeJS - pan camera vertically without tilting?

I am using Mr Doob's periodic table code in my web app:
https://threejs.org/examples/css3d_periodictable.html
I am using it in Helix view. When I rotate the object left, I shift the camera's Y position by a certain amount too. My desire is to give the impression that the Helix is corkscrewing vertically up and down as you rotate the camera. This is the code I'm using, where angle and panAmount are constants that control how much rotation and vertical pan takes place per second:
let g_RotationMatrix = new THREE.Matrix4();
g_RotationMatrix.makeRotationY(angle);
// Apply matrix like this to rotate the camera.
self.object.position.applyMatrix4(g_RotationMatrix);
// Shift it vertically too.
self.object.position.y += panAmount;
// Make camera look at the target.
self.object.lookAt(self.target);
The problem I'm having is that from the camera's perspective, the object appears to tilt towards you and away from you respectively, depending on the rotation direction, as the camera shifts vertically. This makes sense to me because the I'm guessing that the lookat() function causes the camera to look at the center of the target, and not at point on the target that is closest point to it, so the camera has to tilt to focus on the targe's center of mass. I see the same effect when I use the mouse to pan vertically using the Orbit controls. I believe another way to describe the effect is that the object appears to pitch up and down as the camera shifts vertically.
The effect I want instead is that of a window washer on an automated lift being raised up and down the side of building, with the side of the building appearing perfectly flat to the camera regardless of the camera's current Y position.
How can I achieve this effect with the camera?
Make the camera lookAt the target, but at the same y level as the camera.
Assuming self.target is a vector3 object and self.object is the camera:
If, for example, self.target is the camera's rotation center of the object, you wouldn't want to change the actual self.target vector. Make a copy of it first.
const newTarget = new THREE.Vector3( );
function render( ){
// copy the target vector to newTarget so that the original self.target
// will not change and the camera can still rotate around the original
// target.
newTarget.copy( self.target );
// Set newTarget's Y from the camera Y. So that is looks horizontal.
newTarget.y = self.object.position.y;
// Make the camera look at the objects newTarget
self.object.lookAt( newTarget);
}

THREE.js Orthographic camera position not updating after *dolly* with OrbitControl

I'm using THREE.OrbitControls to dolly a THREE.OrthographicCamera. But, even thought the ortho camera renders correctly as repositioned, all that is updating on the orthographic camera is the 'zoom' property. Even after calling camera.updateProjectionMatrix(). Do I need to manually update the 'position' property of the camera based on the updated 'zoom' property? I want to display its position in my UI after dollying it.
(Note, this is a rewrite of my other question,THREE.js Orthographic camera position not updating after zoom with OrbitControl, in which I thought I was zooming with the OrbitControl but was actually dollying. Sorry about this).
Dollying in/out with an ortho cam would have an unnoticeable effect. With ortho cams there is no perception of proximity because it has no perspective. All objects appear the same in size regardless of distance from the lens because the projection rays are all parallel. The only difference you'd notice is when the objects get clipped because they're past the near or far plane.
So, the decision was made that scrolling with OrbitControls would change the zoom of the camera, narrowing in/out of the center.
If you want to force the camera to move further/closer of its focus point, you could just translate it back/forth in the z-axis with:
camera.translateZ(distance); A (-) distance would move it closer, and a (+) distance would move it further from its focus point.

Extrinsic parameters of camera - are they constant?

I am wondering how can the extrinsic parameters of a camera be constant?
I know that the rotation matrix aligns the world coordinate system axises to the camera coordinate system, and the translation matrix/vector aligns the origo on top of each other.
But how can the parameters be constant? Would it not somehow be required that I know the orientation of the camera in world space? I.e. by an accelerometer or something?
I hope someone can help me wrap my head around this.
As you have correctly pointed out, camera extrinsics consist of a rotation and a translation of the camera's coordinate system relative to some world coordinate system. So, the extrinsics are constant only as long as the camera does not move relative to the world coordinates. As soon as your camera moves, its extrinsics change.
When you calibrate your camera, you typically use multiple images of a planar calibration pattern. During the calibration process the extrinsics of each location of the calibration pattern are computed. Once the camera is calibrated, you can compute the extrinsics by detecting some reference points with known world coordinates in the image. See this example in MATLAB.

Three.js place an object in rotating camera's fov

I have a fixed-position, perspective camera that rotates around all 3 axes via keyboard input. At random intervals, independent of user input, I need to place objects within the camera's field of view no matter what direction the camera is looking. The objects will also need to be offset specific x and y distances from the center of the camera's fov and offset a specific z distance from the camera's position. I cannot use camera.addChild because once the object is added I need to move the object via tweening independent of the camera's movements.
How can this be done?
You want to transform a point from camera space to world space.
In the camera's coordinate system, the camera is located at the origin, and is looking down its negative z-axis.
Place the object in front of the camera (in the camera's coordinate system).
object.position.set( x, y, - z ); // z is the distance in front of the camera, and is positive
Now, transform the object's position from camera space to world space:
object.position.applyMatrix4( camera.matrixWorld );
three.js r.69

Resources