How to Effectively Manage Cannon Body Rotation Using Quaternions?

I'm facing a tricky problem that I need help with. I am attempting to rotate a Cannon.Body based on mouse input, using the Three FPS example by Cannon as a demonstration of the issue.

Check out the code here View the GitHub repo here

When you run the code and activate pointerlockcontrols by clicking the "click to play" area, then press W for a second to bring the sphere into view of the camera, you'll notice that the sphere moves according to the WASD keys with velocity. Moving the mouse applies quaternion rotation to the Body, calculating proper velocity. However, after turning 180 degrees, the rotation on the X axis is somehow negated. When moving the mouse up, the sphere rotates down.

How can I resolve this issue? Could there be something else in the code interfering with the quaternion?

It might be worth noting that in the playercontroller (pl.js), I apply rotation to the sphereBody instead of the yaw- and pitchObjects.

Snippet from pl.js (Line 49):

var onMouseMove = function ( event ) {

    if ( scope.enabled === false ) return;

    var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
    var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;


    cannonBody.rotation.y -= movementX * 0.002;
    cannonBody.rotation.x -= movementY * 0.002;

    cannonBody.rotation.x = Math.max( - PI_2, Math.min( PI_2, cannonBody.rotation.x ) );

};



<p>And (Line 174):</p>

<pre><code>euler.x = cannonBody.rotation.x;
euler.y = cannonBody.rotation.y;
euler.order = "XYZ";
quat.setFromEuler(euler);
inputVelocity.applyQuaternion(quat);
cannonBody.quaternion.copy(quat);
velocity.x = inputVelocity.x;
velocity.z = inputVelocity.z;

In animate() function in codepen (Line 305):

testballMesh.position.copy(sphereBody.position);
testballMesh.quaternion.copy(sphereBody.quaternion);

Answer №1

The issue lies in the way angles are assigned to and from Quaternions. The properties x, y, z, w of a quaternion do not directly translate to angles, necessitating a conversion step.

Here is how you can specify the angle around a specific axis for a CANNON.Quaternion:

var axis = new CANNON.Vec3(1,0,0);
var angle = Math.PI / 3;
body.quaternion.setFromAxisAngle(axis, angle);

Instead of extracting Euler angles from quaternions, it might be more efficient to store the rotation around X and Y axes when capturing mouse movement:

// Declare variables outside the mouse handler
var angleX=0, angleY=0;

// Within the handler:
angleY -= movementX * 0.002;
angleX -= movementY * 0.002;
angleX = Math.max( - PI_2, Math.min( PI_2, angleX ) );

To convert the rotations into a quaternion, create two separate quaternions (one for X angle and one for Y) then combine them into one:

var quatX = new CANNON.Quaternion();
var quatY = new CANNON.Quaternion();
quatX.setFromAxisAngle(new CANNON.Vec3(1,0,0), angleX);
quatY.setFromAxisAngle(new CANNON.Vec3(0,1,0), angleY);
var quaternion = quatY.mult(quatX);
quaternion.normalize();

To apply this quaternion to your velocity vector:

var rotatedVelocity = quaternion.vmult(inputVelocity);

Remember: Euler angles should be avoided whenever possible to prevent potential complications.

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

Storing the Token from the AJAX Login API Call in JavaScript: Best Practices for Keeping Credentials Secure

After sending my credentials to a login API, I received a successful response containing user data and a token. I would like to know how I can store this information so that the user doesn't have to log in every time. Is it possible for me to save the ...

Update a separate React component in response to the interaction with a different React component

Currently, I am working with a react component named Interest Category that showcases an initial set of Interest categories. Another react component called CreateInterestCategoryDialog, which functions as a modal, is responsible for creating a new entity I ...

Press the button obscured by an image

Recently on my HTML website, I encountered an issue where I tried adding a transparent image over a button but found that I was unable to click on the button afterwards. The problem seems to be related to the following code snippet: #container { heigh ...

Utilizing Async / Await in the created lifecycle hook - Vue2

I recently installed the vue-element-loading package and added its component to my page.vue: <vue-element-loading :active="isActive" :is-full-screen="true"/> After adding a variable to my data: data () { return { isActive: false, } } I th ...

The for loop finishes execution before the Observable in Angular emits its values

I am currently using a function called syncOnRoute() that returns a Promise. This function is responsible for synchronizing my data to the API multiple times based on the length of the data, and it returns a string message each time. However, I am facing a ...

Uncovering unique data points within nested arrays in JavaScript using GraphQL

After receiving GraphQL results, I am faced with a challenge to process them using JavaScript { "data": { "shoeStyleColor": [ { "id": 1, "shoeInventories": [ { "id": 1, "qty": 2, "s ...

Creating a Kendo UI grid within a Kendo UI window and utilizing Knockout JS bindings

I'm encountering an unusual issue while working with Kendo UI and Knockout JS libraries. When attempting to display a kendo grid within a kendo window, the rows inside the grid are being duplicated. Below is a snippet of the code I'm using: JS: ...

Is there a way to retrieve arrays nested within an object in Vue or JavaScript?

In my Vue instance, I have a data object named items <script> export default { data() { return { selected: "", items: { item1: [{ selected: "", inputType: "", inputTarget: "" }], ...

Implementing a click event handler in KendoUI date-time picker to trigger a function when navigating to the previous or next month

Is there a way to trigger an event when the user clicks on the previous/next month buttons in the Kendo UI date time picker? https://i.sstatic.net/ebLOw.png The documentation states that no event is triggered by default in this scenario, so I am attempti ...

What causes Chrome to automatically remove a script tag?

Hello everyone! Instead of utilizing jQuery, I have been creating a script tag and appending it to the head tag in order to retrieve JSONP data. However, after the JSONP callback function is executed, I have noticed that the script tag that I added to the ...

Is there a way to prevent the window.on('beforeUnload') event from triggering when using the <a> tag?

For my project, I require a user confirmation alert to appear when the user attempts to close the window or tab using the X button. However, the window.on('beforeUnload') function also triggers for hyperlinks. How can I prevent the leave page al ...

Implementing automatic 3D model scaling in THREE JS

Incorporated a basic 3D model viewer using three.js. The collection houses a database of 3D models categorized by size - tall, small, and large varieties. The canvas dimensions are fixed on the viewer; this causes some models to load at a small scale initi ...

Selecting objects in Three.js using the camera but without using the mouse

I am working on a Three.js app where I need to determine the object that the perspective camera is focusing on. In order to achieve this, I consulted the raycaster documentation. Most of the resources I came across discuss using raycasting with a camera an ...

Tips on utilizing setInterval in a Vue component

When defining the timer in each individual my-progress, I use it to update the value of view. However, the console shows that the value of the constant changes while the value of the view remains unchanged. How can I modify the timer to successfully change ...

The absence of reactivity is evident when working with composition-api and nuxt3

I've got a Nuxt code snippet that is functioning correctly: <template lang="pug"> div {{ isActive }} !-- Reactivity is working fine, isActive switches from false to true --! </template> <script> export default { data() ...

Looking for Precise Matching within JSON Using JavaScript

I've been experimenting with creating a form that submits data and then checks it against a JSON array to see if there's a matching object already present. Here is a snippet of my JSON data for reference: [ { "ASIN":"B0971Y6PQ3 ...

Searching for a jQuery plugin that can dynamically rearrange tables while automatically updating their corresponding IDs

Is there a way in jQuery to dynamically move tables around on a webpage? Currently, I have implemented a button that clones a hidden table when needed and another button to delete unwanted tables. Now, I am looking to incorporate a feature that allows the ...

Unable to delete data in Laravel 8

I am new to Laravel and facing an issue when trying to delete a row with a modal. The problem is that only the first row is getting removed and I can't figure out the reason. Here is my modal setup: <p class="card-text"><small clas ...

Arranging website elements to conform to a compact grid system

Recently, I've been brainstorming a unique concept for a website layout that involves a background composed of tiny color-shifting squares, each measuring about 10px. The challenge I'm facing is aligning the elements on the page with this grid, a ...

"Can you help me figure out how to transform a date string into a concise date object using JavaScript

As a newcomer to UI coding, I am faced with the challenge of working with date data from JSON in the format "2021-02-28 00:00:00". However, when writing to an xlsx file, I need the date to be in a different format rather than as a string. Here is my attemp ...