Reputation: 20333
I want to "unproject" 2D coordinates back to 3D space, to a given z
plane. (Where z is known, so are the projected 2D coorinates and the pMatrix
and mvMatrix
used).
Web search only shows up with gluUnProject
's variants which has a comletely different use.
Upvotes: 1
Views: 431
Reputation: 20333
First make sure that your screen-coordinates are in the right coordinate-space, that is between -1
and 1
.
Then you need to combine projection and model-view matrices into a single one. Sample code using Javascript and glMatrix for convenience:
var m = mat4.create();
mat4.multiply(m, pMatrix, mvMatrix);
On Wikipedia you can find the basic formula used with projection. Factoring out those multiplications and solving them for x
and y
will give you (screenshot from mxMaxima):
Note the column-major format in indexes.
The JS version of this formula (with x2
and y2
being the projected 2d coordinates, x
and y
being the original 3d ones and original z
was known):
var x=-((m[8]*(m[5]-m[6]*y2)+m[4]*(m[10]*y2-m[9])+(m[6]*m[9]-m[10]*m[5])*x2)*z+m[4]*(m[14]*y2-m[13])-m[12]*m[6]*y2+(m[13]*m[6]-m[14]*m[5])*x2+m[12]*m[5])/(m[4]*(m[2]*y2-m[1])-m[0]*m[6]*y2+(m[1]*m[6]-m[2]*m[5])*x2+m[0]*m[5]);
var y=((m[8]*(m[1]-m[2]*y2)+m[0]*m[10]*y2+(m[2]*m[9]-m[1]*m[10])*x2-m[0]*m[9])*z-m[12]*m[2]*y2+m[0]*m[14]*y2+(m[13]*m[2]-m[1]*m[14])*x2-m[0]*m[13]+m[1]*m[12])/(m[4]*(m[2]*y2-m[1])-m[0]*m[6]*y2+(m[1]*m[6]-m[2]*m[5])*x2+m[0]*m[5]);
As a bonus you can get the distance from the projection plane with:
var w = m[10]*z+m[6]*y+m[2]*x+m[14];
Upvotes: 1