Reputation: 28208
I'm actually working on a script domvertices
which computes the 4 vertices 3d-coordinates of a any DOM element: http://bl.ocks.org/abernier/97a5fb8c1bebacd1958e
var el = document.getElementById('foo');
var vertices = domvertices(el);
console.log(vertices);
outputs:
{
a: {x: , y: , z: },
b: {x: , y: , z: },
c: {x: , y: , z: },
d: {x: , y: , z: }
}
In order to acheive that, I walk the dom up and for each element store the matrix applied to it (cf. ¹).
Finally, I apply the matrices back to the targetted element in the reverse order.
--
Actually it works great!
My only problem is about perspective... For now, I don't take perspective
nor perspective-origin
into account when computing element's matrix¹.
As a result, deformation from perspective isn't taken into account(as a workaround when drawing vertices, I append them into the element subjected to perspective so they are correctly positionned).
I'd like to take perspective
and perspective-origin
when computing element's matrix.
I can easily make a perpective matrix, my problem is when to apply perspective
and perspectiveOrigin
matrix to ¹ ?
What about nested multiple perspective?
¹: Element's matrix is composed as followed (read right to left):
transformOrigin^-1 * transform * transformOrigin * relativePosition * Identity
Any help appreciated.
Upvotes: 2
Views: 405
Reputation: 236
You can find a TypeScript library on github which supports perspective transformations and some common transformation methods like globalToLocal, localToGlobal and localToLocal: jsidea core library. You can find the matrix-extraction in the jsidea.geom.Transform.extractMatrix function. It looks like that:
//subtract transform-origin
matrix.appendPosition(-originX, -originY, -originZ);
//append transform-matrix
matrix.appendCSS(style.transform);
//add transform-origin
matrix.appendPosition(originX, originY, originZ);
//add local position
//Difficult to calc the local position,
//because the offsetParent, offsetLeft and offsetTop are not reliable.
matrix.appendPosition(position.x, position.y, 0);
//subtract the perspective-origin
matrix.appendPosition(-perspectiveOriginX, -perspectiveOriginY, 0);
//apply the perspective (aka focalLength)
matrix.appendPerspective(perspective);
//add perspective-origin
matrix.appendPosition(perspectiveOriginX, perspectiveOriginY, 0);
Under some conditions the library uses multiple matrices for one element. If the element is in a nested-perspective context and the parent is not preserving 3d (transform-style: flat). You can take a look at the at this code.
Upvotes: 1
Reputation: 2747
Your perspective matrix needs to be equivalent to being the left-most matrix in the sequence of applied matrices.
e.g. as taken from nearly all WebGL fragment shaders
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
The projection matrix is on the left.
Upvotes: 2