Rotating camera independently from its parent in Three.js

I have a scenario where an Entity is traversing a CatmullRomCurve3 path, moving left with the left or down arrow keys and right with the right or up arrow keys.

Initially, I encountered an issue where I wanted the Entity to face perpendicular to the path at 90 degrees instead of in the same direction as the path. You can refer to my code for this scenario here. The problem was resolved with this solution.

In essence, I had to incorporate the following code to rotate the entity:

entity.lookAt((point2).sub(point1).applyAxisAngle(axis, -Math.PI * 0.5).add(point1));

Although the entity now rotates correctly, a new issue arose where the camera was not aligning with the entity or moving along with it (I desired a third-person perspective of the entity); however, attaching the camera as a child of the entity solved the problem!

The Current Issue

Now, my objective is to have the entity initially face 90 degrees away from the path, but upon pressing the left or down arrows, I want the entity to face left (along the path as originally intended), and face the opposite direction when the right or up arrows are pressed.

I achieved this by utilizing some conditional statements in the render loop to adjust the value of -Math.PI * 0.5 to either -Math.PI * 2 or -Math.PI * 0.5 for the left and right directions based on the key pressed.

However, this adjustment also influences the camera, which shares the updated lookAt value since it is linked to the entity. I want the camera to maintain its position consistently (facing 90 degrees from the path, just like the entity when stationary).

How can I prevent the camera from rotating/moving/changing its lookAt orientation when the entity rotates?

It seems that any modifications I make to the camera have no effect, as it remains fixed to the entity's orientation.

Appreciate your assistance.

Answer №1

I believe I have comprehended your inquiry correctly:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 20, -20);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var grid = new THREE.GridHelper(300, 30);
grid.position.setZ(100);
scene.add(grid);

var points = [
  new THREE.Vector3(-80, 5, 35),
  new THREE.Vector3(-80, 5, 192.5),
  new THREE.Vector3(80, 5, 192.5),
  new THREE.Vector3(80, 5, 35)
];

var curve = new THREE.CatmullRomCurve3(points);
curve.closed = true;

var curvePoints = curve.getPoints(200);
var geomCurvePath = new THREE.BufferGeometry().setFromPoints(curvePoints);
var matCurvePath = new THREE.LineBasicMaterial({
  color: 0xff0000
});
var CurvePath = new THREE.Line(geomCurvePath, matCurvePath);
scene.add(CurvePath);

var group = new THREE.Group();
scene.add(group);

group.add(camera);

var pointerGeom = new THREE.ConeGeometry(4, 20, 4);
pointerGeom.translate(0, 10, 0);
pointerGeom.rotateX(Math.PI * 0.5);
var pointer = new THREE.Mesh(pointerGeom, new THREE.MeshNormalMaterial());
group.add(pointer);

btnLeft.addEventListener("click", function() {
  turn(Math.PI * 0.5)
});
btnRight.addEventListener("click", function() {
  turn(-Math.PI * 0.5)
});

function turn(angle) {
  pointer.rotation.y += angle;
}

var p1 = new THREE.Vector3();
var p2 = new THREE.Vector3();
var lookAt = new THREE.Vector3();
var axis = new THREE.Vector3(0, 1, 0);
var percentage = 0;

render();

function render() {
  requestAnimationFrame(render);
  percentage += 0.0005;
  curve.getPointAt(percentage % 1, p1);
  curve.getPointAt((percentage + 0.001) % 1, p2);
  lookAt.copy(p2).sub(p1).applyAxisAngle(axis, -Math.PI * 0.5).add(p1); // look at the point 90 deg from the path
  group.position.copy(p1);
  group.lookAt(lookAt);
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}

#buttons {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="buttons">
  <button id="btnLeft">left</button>
  <button id="btnRight">right</button>
</div>

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

Add some TD(s) after the td element

The HTML code I currently have is as follows: <tr> <td class="success" rowspan="1">Viability</td> <td data-rowh="-Checksum">Viability-Checksum</td> </tr> <tr> ...

Utilizing Node Mailer and Sendgrid to send emails in an Angular MEAN stack project with the angular-fullstack framework generated by Yeoman

Trying to figure out the best location for the code responsible for sending an email through a contact form in my Angular App using angular-fullstack MEAN stack from Yeoman. I managed to implement the email sending logic in the app.js file on the server s ...

Trigger an event in Vue with specified parameters

I am attempting to emit a function with parameters in the following way. template: ` <div class="searchDropDown"> <div class="dropdown is-active"> <div class="dropdown-trigger"> <button class="button" aria-haspopup=" ...

Having trouble setting a value in a Vue.js variable

Upon assigning a value retrieved from the firebase collection, I encountered the following error message. Error getting document: TypeError: Cannot set property 'email' of undefined at eval (Profile.vue?5a88:68) Here is the code snippet in que ...

I'm encountering problems when attempting to display the image/png response from an xmlHTTPRequest. Instead of the correct data, I

I have implemented the following code to integrate a captcha generating web service. The response data is successfully obtained, but when I attempt to display the result within a div element, the image appears as distorted text. var xmlHttp = new XMLHtt ...

Transferring information between Vue.js components via data emissions

Greetings from my VueJS Table component! <b-table class="table table-striped" id="my-table" :items="items" :per-page="perPage" :current-page="currentPage" :fields="fields" @row-clicked="test" lg >< ...

When I click on .toggle-menu, I want the data-target to have a toggled class and the other divs to expand

Looking to achieve a functionality where clicking on .toggle-menu will toggle a class on the specified data-target element and expand other divs accordingly. jQuery(document).ready(function() { var windowWidth = jQuery(window).width(); if (win ...

When using AngularJS, encountered an issue where a view was not updating with new data from a $http request

When making a request to the 500px API using $http for popular photos, the response object is successfully returned. However, I am facing difficulty in pushing the retrieved photo items to the view. Below is my current controller code: meanApp.controller ...

``I am experiencing issues with the Ajax Loader Gif not functioning properly in both IE

I am brand new to using ajax and attempting to display a loading gif while my page loads. Interestingly, it works perfectly in Firefox, but I cannot get it to show up in Chrome or IE. I have a feeling that I am missing something simple. The code I am using ...

Is there a way to display errors during jQuery validation?

Is there a specific function that can provide all error messages generated during form validation? I attempted to use the defaultshowerrors() function, but it only shows errors for the current element being validated. Is there a way to retrieve all error ...

What is the purpose of using route('next') within ExpressJS?

In the documentation it states: You can have multiple callback functions that act as middleware and can invoke next('route') to skip the remaining route callbacks. This is useful for setting pre-conditions on a route and then passing control t ...

Retrieve all default and user-defined fields associated with contacts in the CRM 2011 system

In CRM 2011, the contact entities come with a variety of default fields, and I have also included some custom fields. My goal is to retrieve all field names in a JavaScript list. When creating an email template in CRM, you can select fields from a dialog. ...

Is there a way to retrieve the id of a jQuery autocomplete input while inside the onItemSelect callback function?

I am currently utilizing the jquery autocomplete plugin created by pengoworks. You can find more information about it here: Within the function that is triggered when an entry is selected, I need to determine the identifier of the input element. This is i ...

What is the method to show text on hover in angularjs?

I'm a beginner in AngularJS and I'm looking to show {{Project.inrtcvalue}} when the mouse hovers over values. Can anyone guide me on how to achieve this using AngularJS? <table ng-table="tableParams" show-filter="true" class="table" > ...

Issues with object changes not reflecting in Vue.js 2.0 component rendering

I am facing an issue where my object is not updating immediately after a click event. It appears that a manual refresh or clicking on another element is necessary for the changes to take effect. How can I ensure that the object updates without the need for ...

Dynamic Image Grid Created Using JavaScript Glitches

My dilemma involves using JQuery to create an HTML grid of images styled with Flex Boxes. The setup works perfectly on desktop, but when viewing it on mobile devices, the images begin to act strangely - jumping, overlapping, and even repeating themselves i ...

Is it possible to replicate a stale closure similar to React's useEffect hook without the use of the useEffect hook?

I have a good understanding of closures, but I am struggling to grasp how a stale closure can be created in React's useEffect without providing an exhaustive dependencies array. In order to explore this concept further, I am attempting to replicate a ...

How to pass data from a child component to a parent component in React applications

In my search component, I need to pass a variable called "apiUrl" to the parent component. While I have successfully handled events for other parts of the code, I am unsure how to manage this specific variable transfer. The goal is to send the dynamically ...

Utilizing the $scope variable within an event in the Google Maps API

I am having an issue using $scope within this function. Where should I define the argument $scope so that it works properly? Thank you Below is the basic structure of my code with key lines included: myApp.controller('myCtrl', ['$scope&ap ...

Executing several GET requests in JavaScript

Is there a more efficient way to make multiple get requests to 4 different PHP files within my project and wait for all of them to return successfully before appending the results to the table? I have tried nesting the requests, but I'm looking for a ...