Camera position in front of objects

Hello,

I want to be able to change the camera position and view so when a user click some buttons or objects, the user can directly see the top/front/back/left/right of the object with a predetermined distance no mather where the camera is currently oriented/rotated.

I would like to have the same principle as Autocad. The Top View button is showing me the top of the object not the top of the scene, the Front View button is showing me the front of the object, etc.

Initially, when the scene is loaded/built, Z+ is the view from the user above the objects.
The dot represents the center of the scene.
O1, O2, O3 and O4 represent the objects.
A represents seeing the object from an angle(see closest solution below).
F represents what I want to achieve.

When I change the position of the camera(camera.position.set) to the front of the O1 position for example, instead of showing the front of O1, O4 the left, O3 slightly to the right but behind O1 and O2 too far right to be seen, the scene is rotated to the point that if I change the camera position to O4, the scene is almost vertical.

It is like the the camera is showing me the object but always pointing to the direction of the center of the scene instead of having the scene displayed horizontally and showing the object.

I am using the Perspective camera having the same problems with Trackball, Arcball and Orbit controls.

I tried many solutions found on discourse.threejs.org and other sites and none of them worked.
The closest was if I used camera.up with (0,0,1).
The scene was displayed horizontally but the object was display like if I was seeing it from an angle(A) instead of directly in the front(F).

What should I use to achieve what I want having the position and size of the object, the side and the distance the user wants to see the object?

Note that I am using THREE.js for about 2 weeks so I am not that familiar with all the objects, functions and possibilities that are available.

Thanks.

Hi, i’m not sure if I’ve understand correcly what is appening to you but to do it i will, as the trigger for the view change appens, move the camera to the correct position, like if your object is in x=5 y=3 z=7 and you want a top view you can move the camera to x=5 y=10 z=7 and set the camera to look at the object, or if you want to do it by hand you cans et all the rotation of the camera to 0 and and the rotation on one axe to 90 degree to make it look down, and the same for all the other positions and objects.
Remember that if one of the object is not directly a child of the root scene you need to get the world position for the coordinates to be right.

if you have problems try first with only one object and add the others later.

You can use the technique in this sample:

https://threejs.org/examples/?q=mult#webgl_multiple_elements
Or:
https://threejs.org/examples/?q=mult#webgl_multiple_views

to handle rendering the multiple viewports.

You may want to create a unique camera for each of these.

If you are using OrbitControls, beware that it will override your camera facing, since it makes the camera always point to controls.target, so if you want to reposition/re-orient a camera, make sure there isn’t an OrbitControls controlling it.

Fitting a given scene into a camera viewport is a much trickier problem and can be solved badly in a number of ways.

Hello Simone,

Below, is the code that I used.

The position is supposed to be slightly in front of Red or Blue boxes but, here what is displayed:


Instead of something like this:


I hope that the code is formatted correctly.

<!DOCTYPE html>
<html>
<body class="" topmargin="0" leftmargin="0">

<script type="importmap">
  {
    "imports": {
      "three": "./three.js-master/build/three.module.js",
      "three/addons/": "./three.js-master/examples/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from 'three';
  import {TrackballControls} from 'three/addons/controls/TrackballControls.js';

  var intSceneWidth;
  var intSceneHeight;
  var intSceneDepth;
  var intBoxWidth;
  var intBoxHeight;
  var intBoxDepth;
  var center;
  var camera;
  var controls;
  var scene;
  var renderer;
  var matRed;
  var matGreen;
  var matBlue;
  var matWhite;
  var matYellow;
  var matFloor;
  var geoFloor;
  var mesFloor;
  var geoBox;
  var mesBox;
  var posRedBox;
  var posBlueBox;

  intSceneWidth=220000;
  intSceneHeight=280000;
  intSceneDepth=250000;
  intBoxWidth=10000;
  intBoxHeight=10000;
  intBoxDepth=30000;

  renderer=new THREE.WebGLRenderer( { antialias: true });
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  scene=new THREE.Scene();
  scene.background = new THREE.Color( 0x156289 );

  camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,intSceneDepth);
  camera.near=500;
  camera.far=700000;
  camera.updateProjectionMatrix();
  camera.position.set(0,0,intSceneDepth*2);
  controls=new TrackballControls( camera, renderer.domElement,scene );
  controls.maxDistance=700000;
  controls.update();

  matRed=new THREE.MeshBasicMaterial( { color: 0xff0000 } );
  matGreen=new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
  matBlue=new THREE.MeshBasicMaterial( { color: 0x0000ff } );
  matWhite=new THREE.MeshBasicMaterial( { color: 0xffffff } );
  matYellow=new THREE.MeshBasicMaterial( { color: 0xffff00 } );
  matFloor=new THREE.MeshBasicMaterial( { color: 0x7f7f7f } );

  center=new THREE.Vector3();
  center.x=intSceneWidth/2;
  center.y=intSceneHeight/2;

  geoFloor=new THREE.BoxGeometry(intSceneWidth,intSceneHeight,150);
  mesFloor=new THREE.Mesh( geoFloor, matFloor );
  mesFloor.position.set(intSceneWidth/2,intSceneHeight/2,150/2);
  mesFloor.position.sub(center);
  scene.add(mesFloor);

  geoBox=new THREE.BoxGeometry(intBoxWidth,intBoxHeight,intBoxDepth);
  mesBox=new THREE.Mesh( geoBox, matWhite );
  mesBox.position.set(intSceneWidth/2,intSceneHeight/2,intBoxDepth/2);
  mesBox.position.sub(center);
  scene.add(mesBox);

  posRedBox=new THREE.Vector3(80000+intBoxWidth/2,0+intBoxHeight/2,intBoxDepth/2);
  posRedBox.sub(center);
  mesBox=new THREE.Mesh( geoBox, matRed );
  mesBox.position.set(posRedBox.x,posRedBox.y,posRedBox.z);
  scene.add(mesBox);

  mesBox=new THREE.Mesh( geoBox, matYellow );
  mesBox.position.set(75000+intBoxWidth/2,250000+intBoxHeight/2,intBoxDepth/2);
  mesBox.position.sub(center);
  scene.add(mesBox);

  posBlueBox=new THREE.Vector3(0+intBoxWidth/2,42000+intBoxHeight/2,intBoxDepth/2);
  posBlueBox.sub(center);
  mesBox=new THREE.Mesh( geoBox, matBlue );
  mesBox.position.set(posBlueBox.x,posBlueBox.y,posBlueBox.z);
  scene.add(mesBox);

  mesBox=new THREE.Mesh( geoBox, matGreen );
  mesBox.position.set(210000+intBoxWidth/2,110000+intBoxHeight/2,intBoxDepth/2);
  mesBox.position.sub(center);
  scene.add(mesBox);

  animate();

  window.scene=scene;
  window.SetCameraPositionRedBox=SetCameraPositionRedBox;
  window.SetCameraPositionBlueBox=SetCameraPositionBlueBox;
  window.camera=camera;
  window.controls=controls;
  window.addEventListener( 'resize', onWindowResize );

function animate()
{
  requestAnimationFrame( animate );

  controls.update();
  renderer.render( scene, camera );
}

function SetCameraPositionRedBox()
{
  camera.position.set(posRedBox.x,posRedBox.y-35000,15000);
  camera.updateProjectionMatrix();
  controls.update();
}

function SetCameraPositionBlueBox()
{
  camera.position.set(posBlueBox.x,posBlueBox.y-35000,15000);
  camera.updateProjectionMatrix();
  controls.update();
}

function onWindowResize()
{
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize( window.innerWidth, window.innerHeight );
}
</script>

<div style="position:absolute; top:0px; left:0px; color:#ffffff;">
<input type="button" style="white-space:normal; width:150px;" value="Set camera position Red box" onclick="SetCameraPositionRedBox();">
<input type="button" style="white-space:normal; width:150px;" value="Set camera position Blue box" onclick="SetCameraPositionBlueBox();">
</div>
</body>
</html>

Thanks

Hi, without running the code i will say that in the function SetCameraPositionRedBox() and the othres you need to set the camera.target to the object since you are using the trackball camera:
If this do not solve the issue try to set manually the camera rotation like you do for the position.

You mean controls.target?

Yes sorry the control target

1 Like

Yeah that sounds right.

Thanks Simone,

controls.target did what I needed.

I also had to add camera.up=new THREE.Vector3(…) so the view is horizontal instead of rotated.

Again, thanks a lot.

2 Likes