diff --git a/pyrender/camera.py b/pyrender/camera.py index e019358..8577041 100644 --- a/pyrender/camera.py +++ b/pyrender/camera.py @@ -91,6 +91,20 @@ def get_projection_matrix(self, width=None, height=None): """ pass + @abc.abstractmethod + def inverse_transform_depth_ndc(self, depth_ndc): + """ + Unproject the depth in Normalized Device Coordinates + to metric values in eye (camera) reference frame. + :param + depth_ndc: np.array np.float32 + depth in [-1, 1] in normalized device coordinates + :return: + depth: np.array np.float32 + depth in metric units in eye (camera) reference frame. + """ + pass + class PerspectiveCamera(Camera): @@ -205,6 +219,19 @@ def get_projection_matrix(self, width=None, height=None): return P + def inverse_transform_depth_ndc(self, depth_ndc): + inf_inds = (depth_ndc == 1) + noninf = np.logical_not(inf_inds) + depth_img = depth_ndc + if self.zfar is None: + depth_img[noninf] = 2 * self.znear / (1.0 - depth_img[noninf]) + else: + depth_img[noninf] = ((2.0 * self.znear * self.zfar) / + (self.zfar + self.znear - depth_img[noninf] * + (self.zfar - self.znear))) + depth_img[inf_inds] = 0.0 + return depth_img + class OrthographicCamera(Camera): """An orthographic camera for orthographic projection. @@ -309,6 +336,17 @@ def get_projection_matrix(self, width=None, height=None): P[3][3] = 1.0 return P + def inverse_transform_depth_ndc(self, depth_ndc): + inf_inds = (depth_ndc == 1) + noninf = np.logical_not(inf_inds) + depth_img = depth_ndc + if self.zfar is None: + depth_img[noninf] = 2 * self.znear / (1.0 - depth_img[noninf]) + else: + depth_img[noninf] = (depth_img[noninf] * (self.zfar - self.znear) + self.zfar + self.znear) / 2.0 + depth_img[inf_inds] = 0.0 + return depth_img + class IntrinsicsCamera(Camera): """A perspective camera with custom intrinsics. @@ -432,6 +470,19 @@ def get_projection_matrix(self, width, height): return P + def inverse_transform_depth_ndc(self, depth_ndc): + inf_inds = (depth_ndc == 1) + noninf = np.logical_not(inf_inds) + depth_img = depth_ndc + if self.zfar is None: + depth_img[noninf] = 2 * self.znear / (1.0 - depth_img[noninf]) + else: + depth_img[noninf] = ((2.0 * self.znear * self.zfar) / + (self.zfar + self.znear - depth_img[noninf] * + (self.zfar - self.znear))) + depth_img[inf_inds] = 0.0 + return depth_img + __all__ = ['Camera', 'PerspectiveCamera', 'OrthographicCamera', 'IntrinsicsCamera'] diff --git a/pyrender/renderer.py b/pyrender/renderer.py index f212907..0403599 100644 --- a/pyrender/renderer.py +++ b/pyrender/renderer.py @@ -1150,18 +1150,8 @@ def _read_main_framebuffer(self, scene, flags): depth_im = np.frombuffer(depth_buf, dtype=np.float32) depth_im = depth_im.reshape((height, width)) depth_im = np.flip(depth_im, axis=0) - inf_inds = (depth_im == 1.0) depth_im = 2.0 * depth_im - 1.0 - z_near = scene.main_camera_node.camera.znear - z_far = scene.main_camera_node.camera.zfar - noninf = np.logical_not(inf_inds) - if z_far is None: - depth_im[noninf] = 2 * z_near / (1.0 - depth_im[noninf]) - else: - depth_im[noninf] = ((2.0 * z_near * z_far) / - (z_far + z_near - depth_im[noninf] * - (z_far - z_near))) - depth_im[inf_inds] = 0.0 + depth_im = scene.main_camera_node.camera.inverse_transform_depth_ndc(depth_im) # Resize for macos if needed if sys.platform == 'darwin':