From eefb99cbc540e785ee0512e82d4c82209abb184b Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 10 Jan 2013 02:01:39 +0000 Subject: [PATCH] define Lens::extrude_depth() to reverse Lens::project(), and use this in PfmVizzer --- panda/src/distort/cylindricalLens.cxx | 7 +- panda/src/distort/fisheyeLens.cxx | 7 +- panda/src/distort/oSphereLens.cxx | 7 +- panda/src/distort/pSphereLens.cxx | 7 +- panda/src/distort/projectionScreen.cxx | 45 ++++++---- panda/src/gobj/lens.I | 15 ++++ panda/src/gobj/lens.cxx | 43 +++++++-- panda/src/gobj/lens.h | 5 ++ panda/src/gobj/orthographicLens.cxx | 13 +++ panda/src/gobj/orthographicLens.h | 2 + panda/src/gobj/perspectiveLens.cxx | 13 +++ panda/src/gobj/perspectiveLens.h | 2 + panda/src/grutil/pfmVizzer.cxx | 120 +++++++++++++++++-------- 13 files changed, 217 insertions(+), 69 deletions(-) diff --git a/panda/src/distort/cylindricalLens.cxx b/panda/src/distort/cylindricalLens.cxx index e0143c8110..23baab9fd6 100644 --- a/panda/src/distort/cylindricalLens.cxx +++ b/panda/src/distort/cylindricalLens.cxx @@ -149,6 +149,9 @@ do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point PN_stdfloat focal_length = do_get_focal_length(lens_cdata); + // Compute the depth as a linear distance in the range 0 .. 1. + PN_stdfloat z = (pdist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)); + point2d.set ( // The x position is the angle about the Z axis. @@ -156,8 +159,8 @@ do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point // The y position is the Z height divided by the perspective // distance. p[2] * focal_length / pdist, - // Z is the perspective distance scaled into the range (1, -1). - (do_get_near(lens_cdata) - pdist) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)) + // Z is the distance scaled into the range 1 .. -1. + 1.0 - 2.0 * z ); // Now we have to transform the point according to the film diff --git a/panda/src/distort/fisheyeLens.cxx b/panda/src/distort/fisheyeLens.cxx index 6ba58911d3..3818299f0a 100644 --- a/panda/src/distort/fisheyeLens.cxx +++ b/panda/src/distort/fisheyeLens.cxx @@ -198,11 +198,14 @@ do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point PN_stdfloat focal_length = do_get_focal_length(lens_cdata); PN_stdfloat factor = r * focal_length / fisheye_k; + // Compute the depth as a linear distance in the range 0 .. 1. + PN_stdfloat z = (dist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)); + point2d.set (y[0] * factor, y[1] * factor, - // Z is the distance scaled into the range (1, -1). - (do_get_near(lens_cdata) - dist) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)) + // Z is the distance scaled into the range 1 .. -1. + 1.0 - 2.0 * z ); // Now we have to transform the point according to the film diff --git a/panda/src/distort/oSphereLens.cxx b/panda/src/distort/oSphereLens.cxx index fc8bfbb46b..c106073356 100755 --- a/panda/src/distort/oSphereLens.cxx +++ b/panda/src/distort/oSphereLens.cxx @@ -117,14 +117,17 @@ do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point // into the XY plane to do this. LVector2 xy(v3[0], v3[1]); + // Compute the depth as a linear distance in the range 0 .. 1. + PN_stdfloat z = (dist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)); + point2d.set ( // The x position is the angle about the Z axis. rad_2_deg(catan2(xy[0], xy[1])) * focal_length / ospherical_k, // The y position is the Z height. p[2], - // Z is the distance scaled into the range (1, -1). - (do_get_near(lens_cdata) - dist) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)) + // Z is the distance scaled into the range 1 .. -1. + 1.0 - 2.0 * z ); // Now we have to transform the point according to the film diff --git a/panda/src/distort/pSphereLens.cxx b/panda/src/distort/pSphereLens.cxx index 946a8556f5..abf1eb38f9 100644 --- a/panda/src/distort/pSphereLens.cxx +++ b/panda/src/distort/pSphereLens.cxx @@ -115,14 +115,17 @@ do_project(const Lens::CData *lens_cdata, const LPoint3 &point3d, LPoint3 &point xy.normalize(); LVector2d yz(v3[0]*xy[0] + v3[1]*xy[1], v3[2]); + // Compute the depth as a linear distance in the range 0 .. 1. + PN_stdfloat z = (dist - do_get_near(lens_cdata)) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)); + point2d.set ( // The x position is the angle about the Z axis. rad_2_deg(catan2(xy[0], xy[1])) * focal_length / pspherical_k, // The y position is the angle about the X axis. rad_2_deg(catan2(yz[1], yz[0])) * focal_length / pspherical_k, - // Z is the distance scaled into the range (1, -1). - (do_get_near(lens_cdata) - dist) / (do_get_far(lens_cdata) - do_get_near(lens_cdata)) + // Z is the distance scaled into the range 1 .. -1. + 1.0 - 2.0 * z ); // Now we have to transform the point according to the film diff --git a/panda/src/distort/projectionScreen.cxx b/panda/src/distort/projectionScreen.cxx index 5ab3167d21..e578d74d8d 100644 --- a/panda/src/distort/projectionScreen.cxx +++ b/panda/src/distort/projectionScreen.cxx @@ -529,14 +529,14 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) { static const LMatrix4 lens_to_uv (0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f); + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f); static const LMatrix4 lens_to_uv_inverted (0.5f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f); + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f); Thread *current_thread = Thread::get_current_thread(); @@ -546,8 +546,9 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) { const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv; // Iterate through all the vertices in the Geom. + CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread); + vdata = vdata->animate_vertices(true, current_thread); - CPT(GeomVertexData) vdata = geom->get_vertex_data(); CPT(GeomVertexFormat) vformat = vdata->get_format(); if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) { // We need to add a new column for the new texcoords. @@ -582,12 +583,14 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) { LVertex vert = vertex.get_data3(); // For each vertex, project to the film plane. + LPoint3 vert3d = vert * rel_mat; LPoint3 film(0.0f, 0.0f, 0.0f); - bool good = lens->project(vert * rel_mat, film); + bool good = lens->project(vert3d, film); // Now the lens gives us coordinates in the range [-1, 1]. // Rescale these to [0, 1]. - texcoord.set_data3(film * to_uv); + LPoint3 uvw = film * to_uv; + texcoord.set_data3(uvw); // If we have vignette color in effect, color the vertex according // to whether it fell in front of the lens or not. @@ -615,17 +618,18 @@ make_mesh_node(PandaNode *result_parent, const WorkingNodePath &np, const NodePath &camera, LMatrix4 &rel_mat, bool &computed_rel_mat) { PandaNode *node = np.node(); - if (!node->safe_to_flatten()) { - // If we can't safely flatten this node, ignore it (and all of its - // children) completely. It's got no business being here anyway. - return NULL; - } PT(PandaNode) new_node; if (node->is_geom_node()) { new_node = make_mesh_geom_node(np, camera, rel_mat, computed_rel_mat); - } else { + } else if (node->safe_to_flatten()) { new_node = node->make_copy(); + new_node->clear_transform(); + } else { + // If we can't safely flatten the node, just make a plain node in + // its place. + new_node = new PandaNode(node->get_name()); + new_node->set_state(node->get_state()); } // Now attach the new node to the result. @@ -666,9 +670,11 @@ make_mesh_children(PandaNode *new_node, const WorkingNodePath &np, rel_mat, computed_rel_mat); } - // Copy all of the render state (except TransformState) to the - // new arc. - new_child->set_state(child->get_state()); + if (new_child != NULL) { + // Copy all of the render state (except TransformState) to the + // new arc. + new_child->set_state(child->get_state()); + } } } @@ -719,15 +725,16 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) { PT(Geom) new_geom = geom->make_copy(); GeomVertexRewriter vertex(new_geom->modify_vertex_data(), - InternalName::get_vertex()); + InternalName::get_vertex()); while (!vertex.is_at_end()) { LVertex vert = vertex.get_data3(); // Project each vertex into the film plane, but use three // dimensions so the Z coordinate remains meaningful. + LPoint3 vert3d = vert * rel_mat; LPoint3 film(0.0f, 0.0f, 0.0f); - lens->project(vert * rel_mat, film); - + lens->project(vert3d, film); + vertex.set_data3(film); } diff --git a/panda/src/gobj/lens.I b/panda/src/gobj/lens.I index 80fa8df021..47ee2f4e1d 100644 --- a/panda/src/gobj/lens.I +++ b/panda/src/gobj/lens.I @@ -58,6 +58,21 @@ extrude(const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const { return do_extrude(cdata, point2d, near_point, far_point); } +//////////////////////////////////////////////////////////////////// +// Function: Lens::extrude_depth +// Access: Published +// Description: Uses the depth component of the 3-d result from +// project() to compute the original point in 3-d space +// corresponding to a particular point on the lens. +// This exactly reverses project(), assuming the point +// does fall legitimately within the lens. +//////////////////////////////////////////////////////////////////// +INLINE bool Lens:: +extrude_depth(const LPoint3 &point2d, LPoint3 &point3d) const { + CDReader cdata(_cycler); + return do_extrude_depth(cdata, point2d, point3d); +} + //////////////////////////////////////////////////////////////////// // Function: Lens::extrude_vec // Access: Published diff --git a/panda/src/gobj/lens.cxx b/panda/src/gobj/lens.cxx index f430d18f1c..04839e9545 100644 --- a/panda/src/gobj/lens.cxx +++ b/panda/src/gobj/lens.cxx @@ -1242,6 +1242,37 @@ do_extrude(const CData *cdata, return true; } +//////////////////////////////////////////////////////////////////// +// Function: Lens::do_extrude_depth +// Access: Protected, Virtual +// Description: This is the generic implementation, which is based on +// do_extrude() and assumes a linear distribution of +// depth values between the near and far points. +//////////////////////////////////////////////////////////////////// +bool Lens:: +do_extrude_depth(const CData *cdata, + const LPoint3 &point2d, LPoint3 &point3d) const { + LPoint3 near_point, far_point; + bool result = extrude(point2d, near_point, far_point); + point3d = near_point + (far_point - near_point) * point2d[2]; + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: Lens::do_extrude_depth_with_mat +// Access: Protected +// Description: Implements do_extrude_depth() by using the projection +// matrix. This is efficient, but works only for a +// linear (Perspective or Orthographic) lens. +//////////////////////////////////////////////////////////////////// +bool Lens:: +do_extrude_depth_with_mat(const CData *cdata, + const LPoint3 &point2d, LPoint3 &point3d) const { + const LMatrix4 &projection_mat_inv = do_get_projection_mat_inv(cdata); + point3d = projection_mat_inv.xform_point_general(point2d); + return true; +} + //////////////////////////////////////////////////////////////////// // Function: Lens::do_extrude_vec // Access: Protected, Virtual @@ -1572,15 +1603,15 @@ do_compute_film_mat(CData *cdata) { PN_stdfloat scale_x = 2.0f / film_size[0]; PN_stdfloat scale_y = 2.0f / film_size[1]; cdata->_film_mat.set(scale_x, 0.0f, 0.0f, 0.0f, - 0.0f, scale_y, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - -film_offset[0] * scale_x, -film_offset[1] * scale_y, 0.0f, 1.0f); + 0.0f, scale_y, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + -film_offset[0] * scale_x, -film_offset[1] * scale_y, 0.0f, 1.0f); if ((cdata->_user_flags & UF_keystone) != 0) { cdata->_film_mat = LMatrix4(1.0f, 0.0f, cdata->_keystone[0], cdata->_keystone[0], - 0.0f, 1.0f, cdata->_keystone[1], cdata->_keystone[1], - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f) * cdata->_film_mat; + 0.0f, 1.0f, cdata->_keystone[1], cdata->_keystone[1], + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f) * cdata->_film_mat; } do_adjust_comp_flags(cdata, CF_film_mat_inv, CF_film_mat); diff --git a/panda/src/gobj/lens.h b/panda/src/gobj/lens.h index 63e34cc412..ec21a91d1b 100644 --- a/panda/src/gobj/lens.h +++ b/panda/src/gobj/lens.h @@ -62,6 +62,7 @@ PUBLISHED: LPoint3 &near_point, LPoint3 &far_point) const; INLINE bool extrude(const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const; + INLINE bool extrude_depth(const LPoint3 &point2d, LPoint3 &point3d) const; INLINE bool extrude_vec(const LPoint2 &point2d, LVector3 &vec3d) const; INLINE bool extrude_vec(const LPoint3 &point2d, LVector3 &vec3d) const; INLINE bool project(const LPoint3 &point3d, LPoint3 &point2d) const; @@ -216,6 +217,10 @@ protected: virtual bool do_extrude(const CData *cdata, const LPoint3 &point2d, LPoint3 &near_point, LPoint3 &far_point) const; + virtual bool do_extrude_depth(const CData *cdata, const LPoint3 &point2d, + LPoint3 &point3d) const; + bool do_extrude_depth_with_mat(const CData *cdata, const LPoint3 &point2d, + LPoint3 &point3d) const; virtual bool do_extrude_vec(const CData *cdata, const LPoint3 &point2d, LVector3 &vec) const; virtual bool do_project(const CData *cdata, diff --git a/panda/src/gobj/orthographicLens.cxx b/panda/src/gobj/orthographicLens.cxx index 41d75613c9..2dc775b370 100644 --- a/panda/src/gobj/orthographicLens.cxx +++ b/panda/src/gobj/orthographicLens.cxx @@ -64,6 +64,19 @@ write(ostream &out, int indent_level) const { indent(out, indent_level) << get_type() << " film size = " << get_film_size() << "\n"; } +//////////////////////////////////////////////////////////////////// +// Function: OrthographicLens::do_extrude_depth +// Access: Protected, Virtual +// Description: This is the generic implementation, which is based on +// do_extrude() and assumes a linear distribution of +// depth values between the near and far points. +//////////////////////////////////////////////////////////////////// +bool OrthographicLens:: +do_extrude_depth(const CData *cdata, + const LPoint3 &point2d, LPoint3 &point3d) const { + return do_extrude_depth_with_mat(cdata, point2d, point3d); +} + //////////////////////////////////////////////////////////////////// // Function: OrthographicLens::do_compute_projection_mat // Access: Protected, Virtual diff --git a/panda/src/gobj/orthographicLens.h b/panda/src/gobj/orthographicLens.h index 155b09424e..3319177bf8 100644 --- a/panda/src/gobj/orthographicLens.h +++ b/panda/src/gobj/orthographicLens.h @@ -47,6 +47,8 @@ public: virtual void write(ostream &out, int indent_level = 0) const; protected: + virtual bool do_extrude_depth(const CData *cdata, const LPoint3 &point2d, + LPoint3 &point3d) const; virtual void do_compute_projection_mat(Lens::CData *lens_cdata); public: diff --git a/panda/src/gobj/perspectiveLens.cxx b/panda/src/gobj/perspectiveLens.cxx index 8a0d76bfef..9f32caa26f 100644 --- a/panda/src/gobj/perspectiveLens.cxx +++ b/panda/src/gobj/perspectiveLens.cxx @@ -53,6 +53,19 @@ is_perspective() const { return true; } +//////////////////////////////////////////////////////////////////// +// Function: PerspectiveLens::do_extrude_depth +// Access: Protected, Virtual +// Description: This is the generic implementation, which is based on +// do_extrude() and assumes a linear distribution of +// depth values between the near and far points. +//////////////////////////////////////////////////////////////////// +bool PerspectiveLens:: +do_extrude_depth(const CData *cdata, + const LPoint3 &point2d, LPoint3 &point3d) const { + return do_extrude_depth_with_mat(cdata, point2d, point3d); +} + //////////////////////////////////////////////////////////////////// // Function: PerspectiveLens::do_compute_projection_mat // Access: Protected, Virtual diff --git a/panda/src/gobj/perspectiveLens.h b/panda/src/gobj/perspectiveLens.h index 7540630167..8e35c89e74 100644 --- a/panda/src/gobj/perspectiveLens.h +++ b/panda/src/gobj/perspectiveLens.h @@ -39,6 +39,8 @@ public: virtual bool is_perspective() const; protected: + virtual bool do_extrude_depth(const CData *cdata, const LPoint3 &point2d, + LPoint3 &point3d) const; virtual void do_compute_projection_mat(Lens::CData *lens_cdata); virtual PN_stdfloat fov_to_film(PN_stdfloat fov, PN_stdfloat focal_length, bool horiz) const; diff --git a/panda/src/grutil/pfmVizzer.cxx b/panda/src/grutil/pfmVizzer.cxx index b209c5b6bf..f808c5cf17 100644 --- a/panda/src/grutil/pfmVizzer.cxx +++ b/panda/src/grutil/pfmVizzer.cxx @@ -89,55 +89,103 @@ project(const Lens *lens) { void PfmVizzer:: extrude(const Lens *lens) { nassertv(_pfm.is_valid()); - nassertv(lens->is_linear()); static LMatrix4 from_uv(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, - -1.0, -1.0, -1.0, 1.0); - const LMatrix4 &proj_mat_inv = lens->get_projection_mat_inv(); + 0.0, 0.0, 1.0, 0.0, + -1.0, -1.0, 0.0, 1.0); PfmFile result; result.clear(_pfm.get_x_size(), _pfm.get_y_size(), 3); result.set_zero_special(true); - if (_pfm.get_num_channels() == 1) { - // Create an implicit UV coordinate for each point. - LPoint2 uv_scale(1.0, 1.0); - if (_pfm.get_x_size() > 1) { - uv_scale[0] = 1.0 / PN_stdfloat(_pfm.get_x_size()); - } - if (_pfm.get_y_size() > 1) { - uv_scale[1] = 1.0 / PN_stdfloat(_pfm.get_y_size()); - } - for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { - for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { - if (!_pfm.has_point(xi, yi)) { - continue; + if (lens->is_linear()) { + // If the lens is linear (Perspective or Orthographic), we can + // take the slightly faster approach of extruding all the points + // via a transform matrix. + const LMatrix4 &proj_mat_inv = lens->get_projection_mat_inv(); + + if (_pfm.get_num_channels() == 1) { + // Create an implicit UV coordinate for each point. + LPoint2 uv_scale(1.0, 1.0); + if (_pfm.get_x_size() > 1) { + uv_scale[0] = 1.0 / PN_stdfloat(_pfm.get_x_size()); + } + if (_pfm.get_y_size() > 1) { + uv_scale[1] = 1.0 / PN_stdfloat(_pfm.get_y_size()); + } + for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { + for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + LPoint3 p, rp; + p.set(((PN_stdfloat)xi + 0.5) * uv_scale[0], + ((PN_stdfloat)yi + 0.5) * uv_scale[1], + (PN_stdfloat)_pfm.get_point1(xi, yi)); + + from_uv.xform_point_in_place(p); + rp = proj_mat_inv.xform_point_general(p); + result.set_point(xi, yi, rp); + } + } + } else { + // Use the existing UV coordinate for each point. + for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { + for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + LPoint3 p, rp; + p = LCAST(PN_stdfloat, _pfm.get_point(xi, yi)); + + from_uv.xform_point_in_place(p); + rp = proj_mat_inv.xform_point_general(p); + result.set_point(xi, yi, rp); } - LPoint3 p; - p.set(((PN_stdfloat)xi + 0.5) * uv_scale[0], - ((PN_stdfloat)yi + 0.5) * uv_scale[1], - (PN_stdfloat)_pfm.get_point1(xi, yi)); - - from_uv.xform_point_in_place(p); - proj_mat_inv.xform_point_general_in_place(p); - result.set_point(xi, yi, p); } } } else { - // Use the existing UV coordinate for each point. - for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { - for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { - if (!_pfm.has_point(xi, yi)) { - continue; + // If the lens is some non-linear specialty lens, we have to call + // Lens::extrude_depth() to correctly extrude each point. + if (_pfm.get_num_channels() == 1) { + // Create an implicit UV coordinate for each point. + LPoint2 uv_scale(1.0, 1.0); + if (_pfm.get_x_size() > 1) { + uv_scale[0] = 1.0 / PN_stdfloat(_pfm.get_x_size()); + } + if (_pfm.get_y_size() > 1) { + uv_scale[1] = 1.0 / PN_stdfloat(_pfm.get_y_size()); + } + for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { + for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + LPoint3 p, rp; + p.set(((PN_stdfloat)xi + 0.5) * uv_scale[0], + ((PN_stdfloat)yi + 0.5) * uv_scale[1], + (PN_stdfloat)_pfm.get_point1(xi, yi)); + + from_uv.xform_point_in_place(p); + lens->extrude_depth(p, rp); + result.set_point(xi, yi, rp); + } + } + } else { + // Use the existing UV coordinate for each point. + for (int yi = 0; yi < _pfm.get_y_size(); ++yi) { + for (int xi = 0; xi < _pfm.get_x_size(); ++xi) { + if (!_pfm.has_point(xi, yi)) { + continue; + } + LPoint3 p, rp; + p = LCAST(PN_stdfloat, _pfm.get_point(xi, yi)); + + from_uv.xform_point_in_place(p); + lens->extrude_depth(p, rp); + result.set_point(xi, yi, rp); } - LPoint3 p; - p = LCAST(PN_stdfloat, _pfm.get_point(xi, yi)); - - from_uv.xform_point_in_place(p); - proj_mat_inv.xform_point_general_in_place(p); - result.set_point(xi, yi, p); } } }