Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to synchronize the Three.js and HTML/SVG coordinate systems (especially w.r.t. the y-axis)?

I'm combining 3D content with Three.js with HTML and SVG content. The Three.js CSSLoader does a pretty good job synchronizing placement of HTML and SVG content in the 3D world.

But the SVG/HTML coordinate systems are 'left-handed', whereas Three.js coordinate system is 'right-handed'. This basically means that their y-axes are reversed. In SVG/HTML, y/top goes up as you go down the screen, and Three.js uses the more standard mathematical convention of y going down as you go down the screen.

I have to continually convert from one to the other, which is pretty error prone. I know I am not the first to run into this (for example, look here). Has someone come up with a general solution? Here's what I tried:

  1. Do everything in an Object3D with .scale.y = -1. As you may suspect, this turns out to be a disaster. It turns everything inside-out, and don't even try to put your camera in there.

  2. Do everything in an Object3D with .rotate.x = Math.PI. This is more promising, but the z axis is no longer consistent with the HTML concept of z-index. Still, this is what I'm using now.

  3. In HTML, don't use top, use bottom. In SVG, do everything inside a <g transform="scale(1, -1)"> inside a <g transform="translate(0, imageHeight)">. However, I feel this would be more confusing for developers, and the imageHeight has to be kept up to date at all times, which is yet another burden.

Has anyone come up with something better? Perhaps a library to help with this?

like image 747
mhelvens Avatar asked Dec 05 '14 17:12

mhelvens


1 Answers

I would suggest you to use the SVG Global Transform Attribute, if you post an example of your code, i could edit the answer and post the example here, maybe a JSfiddle.

Basically you will need to add the transformation to your SVG, in your case to change the direction of y-axis, you can do a "scale(1,-1)".

See the W3 documentation with examples in the following link: http://www.w3.org/TR/SVG/coords.html#SVGGlobalTransformAttribute

The first common use of this attribute:

Most ProjectedCRS have the north direction represented by positive values of the second axis and conversely SVG has a y-down coordinate system. That's why, in order to follow the usual way to represent a map with the north at its top, it is recommended for that kind of ProjectedCRS to use the ‘svg:transform’ global attribute with a 'scale(1, -1)' value as in the third example below.

They have some examples there too, I hope it solves your problem. :)

like image 52
Jacobi Avatar answered Oct 26 '22 01:10

Jacobi