How to set helix toolkit camera target - helix-3d-toolkit

How can I set the camera target and zoom to the target ?
I have many 3d Visuals with Point3D positions which of course are
transformed so the camera doens't locate the object acurately.

You Can Used CameraController property to Set Camera in a HelixViewport3D
HelixViewport3D HelixViewport3d_1 = new HelixViewport3D();
// after Add objects to HelixViewport3d_1 then set camera...
//...
//...
//set Camera
HelixViewport3d_1.CameraController.CameraUpDirection = new Vector3D(0, 0, 1); // set CameraUpDirection property is optional to have better view !! :)
HelixViewport3d_1.CameraController.CameraTarget = new Point3D(30, 0, 0); // or your Target Object 3D Coordinate
HelixViewport3d_1.CameraController.AddZoomForce(-0.3); // amount of Zoom

Additional to the answer by user4106274:
Here the AddZoomForce() is method set to -0.3 for zoom, because the Target object was in (+x,+y,+Z) locations, and perhaps the CameraLookDirection property was in a contrary location.
In different CameraLookDirection property we should Zoom by:
HelixViewport3d_1.CameraController.AddZoomForce(+0.3); // amount of Zoom

Related

Set initial rotation for OrbitControls()

I have an initial roll, pitch & yaw for my camera and so I update the camera rotation with the respective values and it seems correct.
When I create and update the OrbitControls() the values are lost and I don't see a way to set the initial direction in the OrbitControls() constructor or methods.
I tried creating the controls after I updated my camera and that didn't help.
Is it possible to do this?
// Molly
You can compute the initial lookAt / target into some Vector3 computed with spherical / cartesian conversion
Then set the Orbit controller's target with it and save the state. It will use this target as a reference from now on
// Your initial target
let sphericalTarget = new THREE.Spherical(1, Math.PI / 2 - pitch, yaw)
let target = new THREE.Vector3().setFromSpherical(sphericalTarget)
controls = new THREE.OrbitControls()
controls.target = target
controls.saveState()

How to set initial camera position (Three.js/VR)?

If I do not set initial position to the camera, the WEB borwser and Oculus Go browser behave differently (see images below).
const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
// camera position is Vector3(0, 0, 0)
scene.add( camera );
Pic. 1 - Initial camera position in web browser (e.g. Google Chrome)
Pic. 2 - Initial camera position in VR browser (e.g. default browser of Oculus Go)
It looks like Three.js's scene knows in which environment it runs and automatically adjust the camera position. How can I change the initial position of the camera?
Currently, I am doing somethink like this:
const cameraHolder = new Group();
cameraHolder.add(camera);
cameraHolder.position.set(0, 1, 0);
scene.add(cameraHolder);
but again, it doesn't resolve the issue with different positions in different environments.
I believe this is the behaviour of the reference space. If you use reference space type of *-floor the device knows about how tall you are. The camera y is then set to your device y position, which makes sense. As I couldn't find where to grab the device height from I just set the reference space type to local.
this.renderer.xr.setReferenceSpaceType( 'local' );
For me the scene.add(cameraHolder) was necessary, otherwise the camera wouldn't receive the position/rotation. Old HMDs had the cameras attached to a "head" model, then you would turn the head instead of the camera.
You can use
renderer.xr.addEventListener()
Example
camera = new THREE.PerspectiveCamera(35, width / height, 1, 15);
camera.position.set(0, 0.6, 3); // Set the initial Camera Position.
const cameraGroup = new THREE.Group();
cameraGroup.position.set(0, -1, 1.5); // Set the initial VR Headset Position.
//When user turn on the VR mode.
renderer.xr.addEventListener('sessionstart', function () {
scene.add(cameraGroup);
cameraGroup.add(camera);
});
//When user turn off the VR mode.
renderer.xr.addEventListener('sessionend', function () {
scene.remove(cameraGroup);
cameraGroup.remove(camera);
});

ThreeJS apply properties from one camera to another camera

In my webapp I'm using ThreeJS scenes in different modals/popups/dialogs with different width/height ratios.
Furthermore, I want to use multiple user defined camera settings (rotation, position, lookAt etc.) among these different scenes.
Therefore, I save the camera object via camera.toJSON() when the user clicks a capture camera settings button.
(Before I did this, I saved just the object camera, but unfortunately these objects are quite big and slow down the performance while multiple camera objects get stored. Nevertheless, this approach worked, since I was able to copy all the desired values between the saved camera object and the currently used camera [e.g. current_camera.position.x=saved_camera.position.x and so on])
In every scene I want now to use the saved properties I tried the following:
let m = new THREE.Matrix4();
m.fromArray(saved_camera.object.matrix);
current_camera.applyMatrix(m)
current_camera.updateMatrix();
Unfortunately this doesn't work.
"normal" camera object
camera.toJSON() object
If you're comfortable using matrices, then you can turn off the matrix auto-update that three.js does during the render process, and keep the world matrix up-to-date yourself. (This includes any time you change the camera's orientation, so keep that in mind if you're using some form of mouse interaction to control the camera angle.)
First, turn off automatic matrix updating for your camera by setting the autoUpdateMatrix property to false. You can still use the convenience properties (position, rotation, scale), but you'll have to manually update the world matrix by calling camera.updateMatrixWorld(true);.
Finally, when you're ready to restore a particular camera orientation, simply copy the matrix values using the matrixWorld's copy method.
var origin = new THREE.Vector3();
var theCamera = new THREE.PerspectiveCamera(35, 1, 1, 1000);
theCamera.autoUpdateMatrix = false; // turn off auto-update
theCamera.position.set(10, 10, 10);
theCamera.lookAt(origin);
theCamera.updateMatrixWorld(true); // manually update the matrix!
console.log("Camera original matrix: ", theCamera.matrixWorld.elements.toString());
var saveMatrix = new THREE.Matrix4();
saveMatrix.copy(theCamera.matrixWorld);
// saveMatrix now contains the current value of theCamera.matrixWorld
theCamera.position.set(50, -50, 75);
theCamera.lookAt(origin);
theCamera.updateMatrixWorld(true); // manually update the matrix!
console.log("Camera moved matrix: ", theCamera.matrixWorld.elements.toString());
// theCamera.matrixWorld now holds a value that's different from saveMatrix.
theCamera.matrixWorld.copy(saveMatrix);
// Don't upate the matrix, because you just SET it.
console.log("Camera moved matrix: ", theCamera.matrixWorld.elements.toString());
// theCamera.matrixWorld once again contains the saved value.
<script src="https://threejs.org/build/three.js"></script>
Edit to address OrbitControls:
It looks like OrbitControls uses the convenience properties, rather than gathering the information from the matrix. As such, when you restore a camera position, you'll also need to restore those properties. This is easily done by using decompose on the matrix, and copying the resulting values into the appropriate properties:
var d = new THREE.Vector3(),
q = new THREE.Quaternion(),
s = new THREE.Vector3();
camera.matrixWorld.decompose( d, q, s );
camera.position.copy( d );
camera.quaternion.copy( q );
camera.scale.copy( s );

How to set camera coordinates to object in three.js? Using example "webgl obj + mtl loader"

I have a 3D model in .obj format. However the coordinates for this 3D model are not (0,0,0). This a 3D render of drone imagery so the coordinates are actual georeferenced coordinates.
I'm following the example in Three.js on how to load an obj with its mtl on webgl. I use the original HTML except that I simply replace the obj listed as male02 by CerroPelaoLow and the files are placed in the obj directory. Firefox displays the model correctly but the position is the problem.
Note that this render is generated by a program this way and even though I can manipulate the model with a program such as Meshlab I'd still prefer the minimum manipulation possible.
So how can I use local coordinates of my object or focus the camera and then use a different set of controls?
You can use the boundingSphere or boundingBox of your object's geometry to determine the position and of your camera. I have already implemented a functionality to focus an object or a set objects. So, here I share some code:
// assuming following variables:
// object -> your obj model (THREE.Mesh)
// camera -> PerspectiveCamera
// controls -> I'm also using OrbitControls
// if boundingSphere isn't set yet
object.computeBoundingSphere();
var sphere = object.geometry.boundingSphere.clone();
sphere.applyMatrix4( object.matrixWorld );
// vector from current center to camera position (shouldn't be zero in length)
var s = new THREE.Vector3().subVectors( camera.position, controls.center );
var h = sphere.radius / Math.tan( camera.fov / 2 * Math.PI / 180 );
var newPos = new THREE.Vector3().addVectors( sphere.center, s.setLength(h) );
camera.position.copy( newPos );
controls.center.copy( sphere.center );

How can i achieve exact functionality like pointerlock example in threejs but move around programmatically instead of mouse

How can i achieve THREE.js pointerlock controls example functionality but move around programmatically (values from accelerometer device) instead of mouse movement?
THREE.PointerLockControls (next: Module) works this way:
Module makes a construction yawObject -> pitchObject -> camera (pitchObject is a child of yawObject and camera becomes a child of pitchObject).
You add yawObject (which you could get from Module with yourControls.getObject() function) to your scene (to keep transforms updated).
Module adds 'mousemove' event listener and updates yawObject.rotation.y and pitchObject.rotation.x when you move mouse if yourControls.enabled !== false.
Next if you are interested in actually locking cursor you could do it in your client code as in example.
And to update your camera position you could manipulate yawObject's position (yourControls.getObject().position).
So to manipulate controls without mouse you could setup Module this way:
camera.position.set(0, 0, 0);
camera.rotation.set(0, 0, 0); // THREE.PointerLockControls does this too
var myControls = new THREE.PointerLockControls(camera);
var controlsObject = myControls.getObject();
controlsObject.position.set(myEntryX, myEntryY, myEntryZ); // set starting point
controlsObject.rotation.y = myEntryYaw; // rotate yaw obj
controlsObject.children[0].rotation.x = myEntryPitch; // rotate pitch obj
scene.add(controlsObject);
and then keeping myControls.enabled = false manipulate controlsObject.position, controlsObject.rotation.y, controlsObject.children[0].rotation.x.

Resources