/* transforms clip-space coordinates to object-space coordinates, where z is within range [0.0 - 1.0] from near-plane to far-plane */ Vec3f Node::unproject(float x, float y, float z) const { // get viewport and projection matrix Area viewport = gl::getViewport(); Matrix44f projection = gl::getProjection(); // find the inverse modelview-projection-matrix Matrix44f mvp = projection * mWorldTransform; mvp.invert(0.0f); // map x and y from window coordinates Vec4f in(x, float(viewport.getHeight()) - y - 1.0f, z, 1.0f); in.x = (in.x - viewport.getX1()) / float( viewport.getWidth() ); in.y = (in.y - viewport.getY1()) / float( viewport.getHeight() ); // map to range [-1..1] in.x = 2.0f * in.x - 1.0f; in.y = 2.0f * in.y - 1.0f; in.z = 2.0f * in.z - 1.0f; // Vec4f out = mvp * in; if(out.w != 0.0f) out.w = 1.0f / out.w; Vec3f result; result.x = out.x * out.w; result.y = out.y * out.w; result.z = out.z * out.w; return result; }
//---------------------------------------------------------------------------------------------------------------------- ci::Vec3f View::unproject(const ci::Vec3f& point) { // Find the inverse Modelview-Projection-Matrix Matrix44f mInvMVP = ci::gl::getProjection() * ci::gl::getModelView(); mInvMVP.invert(); // Transform to normalized coordinates in the range [-1, 1] Vec4f pointNormal; ci::Area viewport = ci::gl::getViewport(); pointNormal.x = (point.x - viewport.getX1()) / viewport.getWidth() * 2.0f - 1.0f; pointNormal.y = (point.y - viewport.getY1()) / viewport.getHeight() * 2.0f; pointNormal.z = 2.0f * point.z - 1.0f; pointNormal.w = 1.0f; // Find the object's coordinates Vec4f pointCoord = mInvMVP * pointNormal; if (pointCoord.w != 0.0f) { pointCoord.w = 1.0f / pointCoord.w; } // Return coordinate return Vec3f(pointCoord.x * pointCoord.w, pointCoord.y * pointCoord.w, pointCoord.z * pointCoord.w); }
Matrix44f Matrix44f::inverted( void ) { Matrix44f m = *this; m.invert(); return m; }