Finding the x and y coordinates of a rotated 3D cube using JavaScript

In my quest to create a 3D cube using separate div elements, I am faced with a challenge. Imagine a cube made up of 3*3*3 divs where each div has:

  • X, Y, Z coordinates in the 3D space
  • Rotation angles around the X and Y axes

With this information, I should be able to calculate the 2D perspective projection of the cube. The question is: How do I determine the X and Y coordinates for each div?

On a side note, there is a similar example of such a cube here: . However, I have some concerns about this example:

  • The rotation of the cube seems counterintuitive. When moving the mouse down, the cube rotates up, and horizontal movements always rotate around the same axis.
  • The cube in the example only shows "+" at the corners, whereas I prefer a solid filled cube representation.

Answer №1

There are two distinct responses to your inquiry: a direct solution to your query, and a solution to your dilemma:


In Answer to "How do I calculate the X and Y coordinates of each div?"

Note - The following response is an adaptation of a previous post made for the thread Transform GPS-Points to Screen-Points with Perspective Projection in Android. You can also refer to the Wikipedia article "3D projection" for a broader explanation.

If you wish to perform perspective projection, additional information is required such as the position/orientation of your camera/eye, its field of view angle, and the surface on which you intend to project your cube.

By obtaining this data, you can iterate through your div elements, then their 4 corner vertices, apply rotation transformation and projection to derive 2D coordinates necessary for rendering the elements.

Implementing Rotation

We'll simplify by considering:

  • A vertex A(x_0, y_0, z_0), one of the corners of your div
  • θ and δ representing the angles for desired rotation, specifically the pitch angle and yaw angle (Tayt-Brian angles)

We aim to determine:

  • D(x,y,z), the position of our rotated element

The linearized equations become:

  • x = sin(δ) * y_0 + cos(δ) * x_0
  • y = sin(θ) * z_0 + cos(θ) * (cos(δ) * y_0 − sin(δ) * x_0)
  • z = cos(θ) * z_0 i sin(θ) * (cos(δ) * y_0 − sin(δ) * x_0)

Projection Overview

Given:

  • Our point D(x,y,z)
  • w * h, the dimension of the target surface (innerWidth * innerHeight in this context)
  • A half-angle of view α

Our objective:

  • The coordinates of B on the surface plane (referred to as X and Y)

Note: Similar approach for determining Y.

Application

Key points include:

  • Typically, α = 45deg is utilized, eliminating the need for tan(α) in many scenarios.
  • To preserve aspect ratio, maintain f constant for both X and Y, rather than conducting separate calculations for each.
  • Adjust screen coordinates to align with expected display area ranges.

Tackling the Challenge of Rendering a 3D Cube using div

The previously outlined method may encounter limitations when implementing the projected div elements due to potential distortion affecting their appearance and complicating CSS-based rendering.

For showcasing a 3D DOM cube with rotations and depth perception, consider leveraging CSS3 3D transforms to offload computational tasks to the browser.

Benefits include:

  • Utilization of GPU acceleration for smoother performance compared to JS implementations.
  • Automatic handling of content modifications based on transformations applied.
  • No requirement for extensive mathematical computations.

For dynamic cube rotation, utilize JS to manipulate CSS transforms accordingly.

Illustrative Example

An interactive demo on JSFiddle showcases implementation inspired by the tutorial with added functionality for rotational updates triggered by mouse movements.

Trust this proves beneficial! Goodbye!

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

Initiate modal from sub-component

Right now, I am developing a vue application with a structure that closely resembles the following: <div class="characters"> <Character v-for="character in this.charactersToSearch" :key="character.id" :name="cha ...

Trigger a new tab opening following an ajax response with Javascript

Having trouble opening in a new tab after receiving an ajax response with JavaScript, I attempted using both _newtab and _blank However, neither of them seem to be working. I wonder, Is there a solution available to find the answer? ...

What could be causing my JavaScript loop to only display the final value?

Story Behind the Game In my latest project, I am delving into the world of creating a captivating 2D side-scrolling game using HTML and JavaScript. To ensure smooth gameplay, I have opted to incorporate ES6 for efficient management of all game objects. C ...

Tips for displaying two dynamic variables that are interdependent

For instance: Controller: AllBooks[{ book1:{ hardcover{price:25.99},e-book{price:1.99} } }, book2:{ hardcover{price:60.00},e-book{price:2.99} }]; $scope.bookchoice = function(selectedBook) { $rootScope.choice = selectedBook;} $scope.booktype = functio ...

Is it possible to use multiple schemas for one collection name?

I am currently working on creating different schemas for a single collection, such as User or subUser. I aim to store both User and subuser data in the same collection but with different schemas. Here is an example of my schema file: export const AryaSchem ...

Retrieving the body of a GET request using NodeJS and axios

Let me share my request with you: axios.get(BASE_URI + '/birds/random', {Stuff: "STUFF"}) .then(randBird=>{ const birdData = randBird.data const bird = { age: birdData.age, ...

React State Update Triggered by Changing Hidden Input/Textarea Value - No User Input Required

To activate a function when the contents of a hidden input, textarea, or textfield change in React without requiring user input to trigger it, you will need to dynamically adjust the value of the hidden input and then have the function automatically exec ...

Leveraging a function for filtering in AngularJS

I have developed an application where the content filter changes depending on which button is clicked. I have managed to figure out the straightforward filters, but now I am attempting to create a filter that displays content within a specified range. Bel ...

When you refresh the page, the number of items in the cart displayed on the navbar always shows 0

When using my angular application, I encountered a problem with adding movies to a cart. Although I can successfully add them to the cart and see the correct number of movies reflected in the navbar, upon refreshing the page, the count resets to 0. Here i ...

Utilizing data attributes to configure jQuery plugin settings

Having trouble assigning options to an array value in a jQuery plugin using data attributes. When referencing the data attribute with a class selector: $('.tm-input').tagsManager( { prefilled: $('.tm-input').data('loa ...

Is there a method I can use to transform this PHP script so that I can incorporate it in .JS with Ajax?

I have a JavaScript file hosted on domain1.com, but in order for it to function properly, I need to include some PHP code at the beginning. This is necessary to bypass certain restrictions on Safari for my script by creating a session. The PHP code establi ...

Dealing with numerous https requests within a node.js application

I've been searching around on SO for assistance with this issue, but I seem to be going in circles without making any progress. My current project involves making multiple ReST POST requests using node.js https. I need to keep track of the responses ...

Using jQuery to remove an iframe upon a click event

My goal is to remove an iframe whenever anything on the page is clicked. I tried using this code: $('*').on('click',function(){ $('iframe').remove(); }); However, I encountered a problem where the i ...

Generating fresh instances in for loop - JS

I am working on a page that showcases graphs based on selected criteria. Each graph requires its own object reference, and I am creating new objects within a for loop. However, I'm facing the challenge of accessing those objects outside of that specif ...

Guide for displaying d3.js chart using a vue.js method and specifying the target div

I'm working on my Vue code and here's a snippet of what I have: new Vue({ el : '#friendlist', data : { friends : [] }, methods : { fetchStats : function(){ const axios_data = { ...

Ways to convert a jQuery object into HTML that can be utilized?

When running the code below, an alert message of "object Object" is displayed: var shipImgs = $("#div").children(); alert(shipImgs); The container with id "div" includes a total of 4 children (image tags). <div id="div"> <img src="/imgs/spa ...

Node.js seems to be having trouble with emitting events and catching them

I'm having trouble troubleshooting my code. // emitter.js var EventEmitter = require('events').EventEmitter; var util = require('util'); function Loadfun(param1, param2, db){ function __error(error, row){ if(error){ ...

Using `ngRepeat` on a different array of values for repetition

Working with AngularJS. Here is an example of a JSON object: "skills": { "Charisma": {}, "Dexterity": { "Sk3": [ [ true, true, true, true, false ], 44 ] }, ... And the corresponding HTML: <div class="pan ...

Bizarre Object notation with JavaScript

While browsing through a Library called WebApp.net, I stumbled upon this interesting piece of code: var $h = { get HEAD() { return 0 }, get BACK() { return 1 }, get HOME() { return 2 }, get LEFT() { return 3 }, get RIGHT() { return 4 } ...

Does the execution of node.js event handlers occur when the calling stack is clear?

My belief that code related to node.js events is asynchronous was challenged when I came across the following example: var EventEmitter = require('events').EventEmitter; var emitter = new EventEmitter(); emitter.on('foo', function () ...