Adjust the camera in threejs to be positioned inside a different object

My goal is to adjust the camera controlled by trackballControl to match the position of an object.

Currently, it's functioning correctly but as demonstrated in this example, each time the camera changes its position, the z value also changes, which is not the desired behavior.

I am attempting to maintain the same position while only rotating the globe to align with the position of the cube.

Below is my current code:

// Code truncated for brevity
var init = function () {
    // Initialization logic here
};

var render = function () {
    // Rendering logic here
};

var animate = function () {
    // Animation logic here
};

init();
animate();

You can try out the functionality in this demo.

Answer №1

Check out this interactive demo where the camera zooms out when you click a button. JS Fiddle Demo

// Set up variables for camera, scene, renderer, controls, and cubeMesh
document.querySelector('button').onclick = function () {
    let x = cubeMesh.position.x;
    let y = cubeMesh.position.y;
    let z = cubeMesh.position.z;

    // Adjust camera position
    camera.position.x = 0;
    camera.position.y = y + 200;
    camera.position.z = z + 100;
    camera.lookAt(controls.target);
};

// Initialize lights in the scene
var initLights = function () {
    // Add directional and ambient lighting
    var light1 = new THREE.DirectionalLight(0xffffff);
    light1.position.set(1, 1, 1);
    scene.add(light1);

    var light2 = new THREE.DirectionalLight(0x002288);
    light2.position.set(-1, -1, -1);
    scene.add(light2);

    var light3 = new THREE.AmbientLight(0x222222);
    scene.add(light3);
};

// Main initialization function
var init = function () {
    // Set up renderer, camera, and scene
    renderer = new THREE.WebGLRenderer({antialias: false});
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 300;
    scene = new THREE.Scene();

    // Set up trackball controls
    controls = new THREE.TrackballControls(camera);
    controls.target.set(0, 0, 0);
    controls.rotateSpeed = 2;

    document.body.appendChild(renderer.domElement);

    // Create sphere and cube meshes
    var sphereGeom = new THREE.SphereGeometry(100, 32, 32);
    var sphereMat = new THREE.MeshPhongMaterial({
        color: 0xfb3550,
        flatShading: true
    });
    var sphereMesh = new THREE.Mesh(sphereGeom, sphereMat);

    var cubeDim = 20;
    var cubeGeom = new THREE.BoxGeometry(cubeDim, cubeDim, cubeDim);
    var cubeMat = new THREE.MeshPhongMaterial({
        color: 0x7cf93e,
        flatShading: true
    });
    cubeMesh = new THREE.Mesh(cubeGeom, cubeMat);

    // Position and rotate cube mesh
    var spherical = new THREE.Spherical();
    spherical.set(100 + cubeDim / 2, 0.4, 0);
    cubeMesh.position.setFromSpherical(spherical);

    var zero = new THREE.Vector3(0, 0, 0);
    cubeMesh.lookAt(zero);

    // Add meshes to the scene
    scene.add(sphereMesh);
    sphereMesh.add(cubeMesh);

    initLights();
};

// Render function
var render = function () {
    console.log(camera.position);
    renderer.render(scene, camera);
};

// Animation loop
var animate = function () {
    requestAnimationFrame(animate);
    controls.update();
    render();
};

init();
animate();

Answer №2

To change the camera focus to a specific position, you need to set the camera target at that location.

var newTarget = new THREE.Vector3(0, 0, 0);
newTarget.copy(cubeMesh.position);
camera.lookAt(newTarget);

Additionally, inform the THREE.TrackballControls to update according to the camera's changes using THREE.TrackballControls.update:

document.querySelector('button').onclick = function () {
    var newTarget = new THREE.Vector3(0, 0, 0);
    newTarget.copy(cubeMesh.position);
    controls.reset();
    camera.lookAt(newTarget)
    camera.updateProjectionMatrix();
    controls.update();
};


If you wish to maintain the current camera position without resetting it, retrieve the position from the world matrix of the camera and then assign the initial position to the current one:

document.querySelector('button').onclick = function () 
    var newPosition = new THREE.Vector3(0, 0, 0);
    newPosition.applyMatrix4( camera.matrixWorld );
    var newTarget = new THREE.Vector3(0, 0, 0);
    newTarget.copy(cubeMesh.position);
    controls.reset();
    camera.position.copy(newPosition);
    camera.lookAt(newTarget)
    camera.updateProjectionMatrix();
    controls.update();
};


You can refer to the example below for implementation:

(previously provided code snippet remains unchanged)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Dynamically inserting templates into directives

I've been attempting to dynamically add a template within my Angular directive. Following the guidance in this answer, I utilized the link function to compile the variable into an HTML element. However, despite my efforts, I haven't been success ...

Is there a way to incorporate a loading spinner into a MaterialUI DataTable without having to specify a fixed height for the parent component?

Currently, I am using a MaterialUI DataTable with the following setup: <div style = {{height: 300}}> <DataGrid loading={true} getRowHeight={() => "auto"} getEstimatedRowHeight={() => 250} ...

Setting up ESLint for TypeScript with JSX configuration

I am encountering problems with TypeScript configuration. Below is the code snippet from my tsconfig.json: { "compilerOptions": { "target": "es5", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLib ...

Obtain the real-time inventory quantity of the specific product variation in WooCommerce

When a WooCommerce product variation's stock quantity is 0 or less and backorders are allowed, I want to offer customers the option to pre-order the item on the product page. To clearly indicate this to customers, the "Add to Cart" button should chan ...

Restrict access to PHP scripts to only be allowed through AJAX requests

Within my content management system (CMS), I have a specific page that fetches various mini-interfaces from PHP files located in an /ajax directory using AJAX. I am wondering if there is a way to restrict access to these files solely through AJAX requests ...

How come the splice method is changing the value of the original object?

There's something strange happening with this code I'm trying out. Code: const x = [{ a: 'alpha', b: 'beta' }, { a: 'gamma' }]; const y = x[0]; y.a = 'delta'; x.splice(1, 0, y) console.log(x) Output: [ ...

Tips for sequentially arranging and rearranging an array of numbers, even when duplicates are present

Encountered a perplexing issue that has me scratching my head in an attempt to visualize a solution. Currently, I am working with an array of objects that appears as follows: let approvers = [{order:1, dueDate: someDate},{order:2, dueDate: someDate}, ...

Starting object arrays in Angular 6 using ES6

As someone who is just starting out with javascript, I have encountered a challenge with a nested class structure. Specifically, I am looking to initialize an array of EventDate objects and assign it to 'this.dates' within the CustomerEvents cons ...

Tips for importing a JavaScript file from a URL and initializing a class in a React component

I am looking to incorporate the PitchPrint app into a React website. They offer a tutorial for vanilla HTML/JS integration here. Following their instructions, I included script tags with links to jQuery and their app file in my index.html file. I then crea ...

What is the best way to locate a user-provided string within word boundaries using JavaScript regex?

Employing JavaScript, I am currently searching a body of text. Users are given the option to input any string they desire, and then I aim to search for that specific string, ensuring it is considered a "whole word" located between boundaries. All I need i ...

Using AngularJS with the Phonegap Facebook plugin

I am looking to build a Javascript app and deploy it on Android and iOS using Phonegap. My goal is to integrate Facebook login into the app. After exploring the phonegap-facebook plugin, I was able to successfully implement the Facebook login feature. How ...

React does not recognize data.map as a function

Currently, I am facing an issue with a simple map function in React that is supposed to create a set amount of times. {times.map((time) => ( <Pill value={time} handleTimes={handleTimes} key={time} /> ))} The error being thrown i ...

Meteor application: The correct method for fetching a single document from a collection on the client side

Currently in my meteor app, I am saving the unique id of the client within a collection named UserNavigationTracker: { "clientId" : "xxNfxxPGi7tqTbxc4", "currentWizard" : "IntroductionWizard", "currentStep" : "Step-1", "_id" : "ifBJ688upEM ...

What is the process of transforming a JSON string into a JavaScript date object?

{"date":"Thu Dec 06 14:56:01 IST 2012"} Is it possible to convert this JSON string into a JavaScript date object? ...

Error message: The protocol "https:" is not compatible with this function. Please use "http:" instead

I decided to use IBM Bluemix for my school project, where I am working on creating a web service. For my project, I need to fetch JSON data from an API in order to utilize the provided information. Currently, I am utilizing the http get method to retrieve ...

Adding the highcharts-more.src.js file to an Angular 2 project: A step-by-step guide

I have linked highcharts-more to the system variable: 'highcharts-more': 'node_modules/highcharts/highcharts-more.src.js' But I keep getting an error message saying: Error in dev/process/templates/detail.template.html:40:33 ORIGINAL ...

What is the best way to utilize Typescript when making queries to Firebase?

I have successfully integrated push notifications for my app using Firebase Cloud Functions. Now, I am looking to enhance the user experience by updating the app's badge count alongside the push notifications. I understand that this can only be achiev ...

Performing a GET call within the configuration settings of AngularJS

I found a similar question here but unfortunately it didn't solve my issue. I am currently using Angular-UI's Google Maps API, which requires configuration as follows: .config(function(uiGmapGoogleMapApiProvider) { uiGmapGoogleMapApiProvider ...

"Enhancing Your Web Design with Ruby On Rails: Optimal Methods for Integrating CSS

I am a newcomer to Ruby on Rails and I am seeking advice on the best method to incorporate CSS/JS libraries for a specific controller and method in order to avoid unnecessary requests. Currently, I am using the following somewhat inefficient method: - # ...

What is the best way to generate a JavaScript variable using information from SQLite?

I found the examples provided in the JavaScript edition of the Missing Manual series to be extremely helpful! OG.Q. I have explored various options but have not been able to find a solution to my problem yet. This is what I am trying to achieve: Save u ...