Rotating Camera around a Vector3 Point in Three.js

Let me get straight to the point - math is not my strong suit. What may be a piece of cake for you is like solving complex equations in outer space for me.

Currently, I am using Three.js with CSS3DRenderer to construct a virtual art gallery.

What I really need is a first-person perspective, similar to that of a FPS game.

I've managed to make the camera move forward, backward, left, and right successfully.

However, when it comes to rotating the camera, let's just say the results are not what I expected.

The issue lies in my camera rotating on its local axis instead of the viewport itself.

What I truly desire is for the camera to orbit around a specific pivot point/vector, and then readjust its focus using Object3d.lookAt().

I understand that I could simply parent the camera as a child of another object and manipulate the object's axis to achieve this effect. But personally, I prefer to delve into the mathematical calculations myself.

In essence, I want to comprehend how to have one vector point rotate around another, and the mathematical representation behind it.

I am not looking to take the easy route by relying on pre-made scripts like the three.js pointer_lock controls. I am eager to roll up my sleeves and tackle the challenge head-on with pure mathematics.

Any guidance or references to tutorials would be greatly valued and appreciated!

Answer №1

Check out this demonstration of a camera rotating around a box.

The key to making this work is understanding that applying a rotation matrix always rotates an object around the origin. This differs from simply adjusting the rotation property, which rotates the object around its own center. By positioning the camera 200 units away from the origin and then applying the rotation matrix, the camera will rotate in a circular motion around the origin, effectively rotating around the box at the origin. The lookAt function is then used to direct the camera towards the box.

If you're interested in delving deeper into this topic, here's a resource providing a more detailed explanation:

var canvas = document.getElementById('canvas');
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer({canvas: canvas, antialias: true});
var camera = new THREE.PerspectiveCamera(45, canvas.clientWidth / canvas.clientWidth, 1, 1000);

var geometry = new THREE.BoxGeometry(50, 50, 50);
var material = new THREE.MeshBasicMaterial({color: '#f00'});
var box = new THREE.Mesh(geometry, material);
scene.add(box);

// Ensure camera moves forward to prevent spinning in place.
camera.position.z = 200;

var period = 5; // time taken for one full rotation (in seconds)
var clock = new THREE.Clock();
var matrix = new THREE.Matrix4(); // Allocate empty matrix for performance optimization.
render();

function render() {
  requestAnimationFrame(render);
  if (canvas.width !== canvas.clientWidth || canvas.height !== canvas.clientHeight) {
    // Auto-resize mechanism.
    renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
    camera.aspect = canvas.clientWidth /  canvas.clientHeight;
    camera.updateProjectionMatrix();
  }

  // Create a rotation matrix that rotates every 'period' seconds.
  matrix.makeRotationY(clock.getDelta() * 2 * Math.PI / period);

  // Apply the matrix to rotate the camera.
  camera.position.applyMatrix4(matrix);

  // Make camera look at the box.
  camera.lookAt(box.position);

  // Render the scene.
  renderer.render(scene, camera);
}
html, body, #canvas {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
<canvas id="canvas"></canvas>

Answer №2

To efficiently handle positioning and movement of a camera in relation to an object, it is common practice to establish a variable called camera_pivot using the object3D() method at the same coordinates as the object itself. By making the camera a child of this pivot, adjusting its position to create the desired viewing distance, and rotating the object, smooth observations can be achieved.

The flexibility provided by object3D() allows for easy adjustments to both the object's movement and rotation according to specific requirements. This approach not only simplifies coding but also enhances performance.

Utilizing methods like camera_pivot.translateX(), camera_pivot.rotateX(), and camera_pivot.lookAt(obj) on object3D provides further control over the camera's behavior.

In contrast, attempting to manipulate camera and object interactions without utilizing object3D can lead to complications and unintended consequences within the scene.

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

Retrieving a specific id from a meteor-rendered template to access a collection field

UPDATE: I have recently included additional code for clarification, marked as * NEW *. To explain the functionality of this code - it involves inputting a series of data into a collection named posts. The displayed output on the postsList template occurs w ...

"Implementing a method to update an object by its Id within a nested array that includes children, and then managing the state in

How can I dynamically toggle the isExpanded property on click based on an element's ID in a React project? Below is the JSON data structure I am working with const handleExpandOutlineItem = (id: string) => {} This is the structure of my JSON data: ...

What is preventing me from being able to import a React component from a file?

I've double-checked my code and everything seems correct, but when I view it on the port, only the app.js file is displayed. import React from 'react'; import ImgSlider from './ImgSlider'; import './App.css'; function ...

Enhance your jQuery experience by customizing the .click function

When designing my website, I wanted it to be functional on both touch devices and desktops that do not have touch capabilities. To ensure a smooth user experience on touch devices, I implemented the tappy library to eliminate the 300ms delay on jQuery .cli ...

A guide to testing the mui Modal onClose method

When using material UI (mui), the Modal component includes an onClose property, which triggers a callback when the component requests to be closed. This allows users to close the modal by clicking outside of its area. <Modal open={open} onCl ...

Error in GatsbyJS: Unable to retrieve data from property 'childImageFluid' due to undefined value

Currently tackling a Gatsby website, but running into an issue: "TypeError: Cannot read property 'childImageFluid' of undefined" Here's the code snippet from my Project.js file: import React from "react" import PropTypes from &quo ...

Protractor is able to achieve successful test results without actually executing the tests

SYMPTOMS When running Protractor, the tests pass successfully, but the pages do not load. Instead, they appear blank with "data:text/html" in the address bar (refer to the screenshot). Although the tests show as passed, there are 0 assertions being made. ...

Switch up the key while iterating through a JSON object

Can you modify the key while iterating through objects using an external variable? Picture it like this: var data = [{ "id": 1, "name": "Simon", "age": 13 }, { "id": 2, "name": "Helga", "age": 18 }, { "id": 3, "name": "Tom ...

Applying frustum culling to geometric instances

I am currently experiencing an issue with frustum culling. As we all know, frustum culling is default in Three.js, but we have the option to adjust it if necessary. To disable frustum culling, we can set mesh.frustumCulled = false; My problem lies in i ...

Adjust the transparency of a whole section in THREE.js

Is it possible to adjust the transparency of an entire hierarchy (branch) instead of changing the opacity of each individual mesh material separately? ...

Changing Image to Different File Type Using Angular

In my Angular Typescript project, I am currently working on modifying a method that uploads an image using the input element of type file. However, I no longer have an input element and instead have the image file stored in the assets folder of the project ...

Can you show me a comprehensive list of all the REST endpoints for Express mounted Apps?

When working with Express 4, you can utilize the app._router.stack object to list your app routes. In one of the routes in my todos module routes file, I attempted to display this object by sending it as part of the response: exports.update = (req,res) = ...

Is there a way to access the history of Vue routers?

I am looking for a way to determine if the Vue router has additional entries in its history that can be navigated back to. This information is crucial for deciding whether or not to execute the exit app function. The app should only navigate back to prev ...

Can Mutation Observer be utilized in conjunction with a Three.js element in an A-Frame environment?

export class ColliderComponent { constructor() { this.observer = this.createMutationObserver(); this.registerAframeComponent(); } //Registers the AFRAME component. registerAframeComponent(){ const self = this; AFRAME.regi ...

Tips for transferring the button ID value to a GET request?

I recently developed a Node.js application that interacts with a database containing student information and their current marks. Utilizing MongoDB, I retrieve the data and present it in a table within an .ejs file. index.js router.get("/dashboard", funct ...

Manipulate JSON data structure with JavaScript

The initial JSON data: { "data": { "count_at_hub": [ { "hub": "A", "date": "", "size": "1", "count": 141 }, { "hub": "A", "date": "", "size": " ...

Adapt your content to match the current slide of the dynamic Bootstrap Carousel

I recently implemented the basic carousel from the bootstrap website into my web application and encountered a challenge. I want to adjust the content on my site based on the active slide of the carousel... is this achievable? My goal is to display div On ...

React error message: "Cannot update state on a component that is not mounted" unless using the useEffect hook

(I am a beginner using Next.js + Styled Components and need help :)) I'm currently working on creating a "Netflix" style page, with unique catalog components. Each content item in the grid is a complex component named ContentItem.js that is repeated ...

Scrolling to does not function properly with Material UI tabs

Looking for a solution to scroll to a specific div when clicking on a tab in Material UI Tabs using UseRef and ScrollTo. Check out the sandbox link here: https://codesandbox.io/s/exciting-sound-mrw2v Currently, when I click on Tab 2, I expect it to autom ...

What is the best way to invoke a Rest API within a Vue component?

As a newcomer to VueJS, my goal is to create a basic page featuring a pie chart displaying some data. Currently, I have successfully displayed the chart using example data. However, I now wish to populate the chart with data fetched from an API call on my ...