예제 #1
0
    def _updateViewportGeometry(self, width, height):
        view_w = width * self._viewport_rect.width()
        view_h = height * self._viewport_rect.height()

        for camera in self._app.getController().getScene().getAllCameras():
            camera.setViewportSize(view_w, view_h)
            proj = Matrix()
            if camera.isPerspective():
                proj.setPerspective(30, view_w / view_h, 1, 500)
            else:
                proj.setOrtho(-view_w / 2, view_w / 2, -view_h / 2, view_h / 2, -500, 500)
            camera.setProjectionMatrix(proj)

        self._app.getRenderer().setViewportSize(view_w, view_h)
        self._app.getRenderer().setWindowSize(width, height)
예제 #2
0
 def resizeEvent(self, event):
     super().resizeEvent(event)
     
     w = event.size().width() * self.devicePixelRatio()
     h = event.size().height() * self.devicePixelRatio()
     for camera in self._app.getController().getScene().getAllCameras():
         camera.setViewportSize(w, h)
         proj = Matrix()
         if camera.isPerspective():
             proj.setPerspective(30, w/h, 1, 500)
         else:
             proj.setOrtho(-w / 2, w / 2, -h / 2, h / 2, -500, 500)
         camera.setProjectionMatrix(proj)
     self._preferences.setValue("general/window_width", event.size().width())
     self._preferences.setValue("general/window_height", event.size().height())
     self._app.getRenderer().setViewportSize(w, h)
예제 #3
0
    def _updateViewportGeometry(self, width, height):
        view_w = width * self._viewport_rect.width()
        view_h = height * self._viewport_rect.height()

        for camera in self._app.getController().getScene().getAllCameras():
            camera.setViewportSize(view_w, view_h)
            camera.setWindowSize(width, height)
            proj = Matrix()
            if camera.isPerspective():
                proj.setPerspective(30, view_w / view_h, 1, 500)
            else:
                proj.setOrtho(-view_w / 2, view_w / 2, -view_h / 2, view_h / 2, -500, 500)
            camera.setProjectionMatrix(proj)

        self._app.getRenderer().setViewportSize(view_w, view_h)
        self._app.getRenderer().setWindowSize(width, height)
예제 #4
0
    def resizeEvent(self, event):
        super().resizeEvent(event)
        
        w = event.size().width() * self.devicePixelRatio()
        h = event.size().height() * self.devicePixelRatio()
        for camera in self._app.getController().getScene().getAllCameras():
            camera.setViewportSize(w, h)
            proj = Matrix()
            if camera.isPerspective():
                proj.setPerspective(30, w/h, 1, 500)
            else:
                proj.setOrtho(-w / 2, w / 2, -h / 2, h / 2, -500, 500)
            camera.setProjectionMatrix(proj)

        self._app.getRenderer().setViewportSize(w, h)

        QMetaObject.invokeMethod(self, "_onWindowGeometryChanged", Qt.QueuedConnection);
예제 #5
0
 def _updatePerspectiveMatrix(self):
     view_width = self._viewport_width
     view_height = self._viewport_height
     projection_matrix = Matrix()
     if self.isPerspective():
         if view_width != 0 and view_height != 0:
             projection_matrix.setPerspective(30, view_width / view_height, 1, 500)
     else:
         # Almost no near/far plane, please.
         if view_width != 0 and view_height != 0:
             horizontal_zoom = view_width * self._zoom_factor
             vertical_zoom = view_height * self._zoom_factor
             projection_matrix.setOrtho(-view_width / 2 - horizontal_zoom, view_width / 2 + horizontal_zoom,
                                        -view_height / 2 - vertical_zoom, view_height / 2 + vertical_zoom,
                                        -9001, 9001)
     self.setProjectionMatrix(projection_matrix)
     self.perspectiveChanged.emit(self)
예제 #6
0
    def _updateViewportGeometry(self, width: int, height: int):
        view_width = width * self._viewport_rect.width()
        view_height = height * self._viewport_rect.height()

        for camera in self._app.getController().getScene().getAllCameras():
            camera.setWindowSize(width, height)

            if camera.getAutoAdjustViewPort():
                camera.setViewportSize(view_width, view_height)
                projection_matrix = Matrix()
                if camera.isPerspective():
                    if view_width is not 0:
                        projection_matrix.setPerspective(30, view_width / view_height, 1, 500)
                else:
                    projection_matrix.setOrtho(-view_width / 2, view_width / 2, -view_height / 2, view_height / 2, -500, 500)
                camera.setProjectionMatrix(projection_matrix)

        self._app.getRenderer().setViewportSize(view_width, view_height)
        self._app.getRenderer().setWindowSize(width, height)
예제 #7
0
    def _updateViewportGeometry(self, width: int, height: int):
        view_width = width * self._viewport_rect.width()
        view_height = height * self._viewport_rect.height()

        for camera in self._app.getController().getScene().getAllCameras():
            camera.setWindowSize(width, height)

            if camera.getAutoAdjustViewPort():
                camera.setViewportSize(view_width, view_height)
                projection_matrix = Matrix()
                if camera.isPerspective():
                    if view_width is not 0:
                        projection_matrix.setPerspective(30, view_width / view_height, 1, 500)
                else:
                    projection_matrix.setOrtho(-view_width / 2, view_width / 2, -view_height / 2, view_height / 2, -500, 500)
                camera.setProjectionMatrix(projection_matrix)

        self._app.getRenderer().setViewportSize(view_width, view_height)
        self._app.getRenderer().setWindowSize(width, height)
예제 #8
0
파일: Camera.py 프로젝트: greatnam/Uranium
class Camera(SceneNode.SceneNode):
    class PerspectiveMode(enum.Enum):
        PERSPECTIVE = "perspective"
        ORTHOGRAPHIC = "orthographic"

    @staticmethod
    def getDefaultZoomFactor() -> float:
        return -0.3334

    def __init__(self,
                 name: str = "",
                 parent: Optional[SceneNode.SceneNode] = None) -> None:
        super().__init__(parent)
        self._name = name  # type: str
        self._projection_matrix = Matrix()  # type: Matrix
        self._projection_matrix.setOrtho(-5, 5, -5, 5, -100, 100)
        self._perspective = True  # type: bool
        self._viewport_width = 0  # type: int
        self._viewport_height = 0  # type: int
        self._window_width = 0  # type: int
        self._window_height = 0  # type: int
        self._auto_adjust_view_port_size = True  # type: bool
        self.setCalculateBoundingBox(False)
        self._cached_view_projection_matrix = None  # type: Optional[Matrix]

        self._zoom_factor = Camera.getDefaultZoomFactor()

        from UM.Application import Application
        Application.getInstance().getPreferences().addPreference(
            "general/camera_perspective_mode",
            default_value=self.PerspectiveMode.PERSPECTIVE.value)
        Application.getInstance().getPreferences().preferenceChanged.connect(
            self._preferencesChanged)
        self._preferencesChanged("general/camera_perspective_mode")

    def __deepcopy__(self, memo: Dict[int, object]) -> "Camera":
        copy = cast(Camera, super().__deepcopy__(memo))
        copy._projection_matrix = self._projection_matrix
        copy._window_height = self._window_height
        copy._window_width = self._window_width
        copy._viewport_height = self._viewport_height
        copy._viewport_width = self._viewport_width
        return copy

    def getZoomFactor(self):
        return self._zoom_factor

    def setZoomFactor(self, zoom_factor: float) -> None:
        # Only an orthographic camera has a zoom at the moment.
        if not self.isPerspective():
            if self._zoom_factor != zoom_factor:
                self._zoom_factor = zoom_factor
                self._updatePerspectiveMatrix()

    def setMeshData(self, mesh_data: Optional["MeshData"]) -> None:
        assert mesh_data is None, "Camera's can't have mesh data"

    def getAutoAdjustViewPort(self) -> bool:
        return self._auto_adjust_view_port_size

    def setAutoAdjustViewPort(self, auto_adjust: bool) -> None:
        self._auto_adjust_view_port_size = auto_adjust

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self) -> Matrix:
        return self._projection_matrix

    def getViewportWidth(self) -> int:
        return self._viewport_width

    def setViewportWidth(self, width: int) -> None:
        self._viewport_width = width
        self._updatePerspectiveMatrix()

    def setViewportHeight(self, height: int) -> None:
        self._viewport_height = height
        self._updatePerspectiveMatrix()

    def setViewportSize(self, width: int, height: int) -> None:
        self._viewport_width = width
        self._viewport_height = height
        self._updatePerspectiveMatrix()

    def _updatePerspectiveMatrix(self) -> None:
        view_width = self._viewport_width
        view_height = self._viewport_height
        projection_matrix = Matrix()
        if self.isPerspective():
            if view_width != 0 and view_height != 0:
                projection_matrix.setPerspective(30, view_width / view_height,
                                                 1, 500)
        else:
            # Almost no near/far plane, please.
            if view_width != 0 and view_height != 0:
                horizontal_zoom = view_width * self._zoom_factor
                vertical_zoom = view_height * self._zoom_factor
                projection_matrix.setOrtho(-view_width / 2 - horizontal_zoom,
                                           view_width / 2 + horizontal_zoom,
                                           -view_height / 2 - vertical_zoom,
                                           view_height / 2 + vertical_zoom,
                                           -9001, 9001)
        self.setProjectionMatrix(projection_matrix)
        self.perspectiveChanged.emit(self)

    def getViewProjectionMatrix(self) -> Matrix:
        if self._cached_view_projection_matrix is None:
            inverted_transformation = self.getWorldTransformation()
            inverted_transformation.invert()
            self._cached_view_projection_matrix = self._projection_matrix.multiply(
                inverted_transformation, copy=True)
        return self._cached_view_projection_matrix

    def _updateWorldTransformation(self) -> None:
        self._cached_view_projection_matrix = None
        super()._updateWorldTransformation()

    def getViewportHeight(self) -> int:
        return self._viewport_height

    def setWindowSize(self, width: int, height: int) -> None:
        self._window_width = width
        self._window_height = height

    def getWindowSize(self) -> Tuple[int, int]:
        return self._window_width, self._window_height

    def render(self, renderer) -> bool:
        # It's a camera. It doesn't need rendering.
        return True

    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix: Matrix) -> None:
        self._projection_matrix = matrix
        self._cached_view_projection_matrix = None

    def isPerspective(self) -> bool:
        return self._perspective

    def setPerspective(self, perspective: bool) -> None:
        if self._perspective != perspective:
            self._perspective = perspective
            self._updatePerspectiveMatrix()

    perspectiveChanged = Signal()

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x: float, y: float) -> Ray:
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        inverted_projection = numpy.linalg.inv(
            self._projection_matrix.getData().copy())
        transformation = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype=numpy.float32)
        near = numpy.dot(inverted_projection, near)
        near = numpy.dot(transformation, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype=numpy.float32)
        far = numpy.dot(inverted_projection, far)
        far = numpy.dot(transformation, far)
        far = far[0:3] / far[3]

        direction = far - near
        direction /= numpy.linalg.norm(direction)

        if self.isPerspective():
            origin = self.getWorldPosition()
            direction = -direction
        else:
            # In orthographic mode, the origin is the click position on the plane where the camera resides, and that
            # plane is parallel to the near and the far planes.
            projection = numpy.array([view_x, -view_y, 0.0, 1.0],
                                     dtype=numpy.float32)
            projection = numpy.dot(inverted_projection, projection)
            projection = numpy.dot(transformation, projection)
            projection = projection[0:3] / projection[3]

            origin = Vector(data=projection)

        return Ray(origin, Vector(direction[0], direction[1], direction[2]))

    ##  Project a 3D position onto the 2D view plane.
    def project(self, position: Vector) -> Tuple[float, float]:
        projection = self._projection_matrix
        view = self.getWorldTransformation()
        view.invert()

        position = position.preMultiply(view)
        position = position.preMultiply(projection)
        return position.x / position.z / 2.0, position.y / position.z / 2.0

    ##  Updates the _perspective field if the preference was modified.
    def _preferencesChanged(self, key: str) -> None:
        if key != "general/camera_perspective_mode":  # Only listen to camera_perspective_mode.
            return
        from UM.Application import Application
        new_mode = str(Application.getInstance().getPreferences().getValue(
            "general/camera_perspective_mode"))

        # Translate the selected mode to the camera state.
        if new_mode == str(self.PerspectiveMode.ORTHOGRAPHIC.value):
            Logger.log("d", "Changing perspective mode to orthographic.")
            self.setPerspective(False)
        elif new_mode == str(self.PerspectiveMode.PERSPECTIVE.value):
            Logger.log("d", "Changing perspective mode to perspective.")
            self.setPerspective(True)
        else:
            Logger.log(
                "w", "Unknown perspective mode {new_mode}".format(
                    new_mode=new_mode))
예제 #9
0
class Camera(SceneNode.SceneNode):
    def __init__(self,
                 name: str = "",
                 parent: SceneNode.SceneNode = None) -> None:
        super().__init__(parent)
        self._name = name  # type: str
        self._projection_matrix = Matrix()  # type: Matrix
        self._projection_matrix.setOrtho(-5, 5, 5, -5, -100, 100)
        self._perspective = True  # type: bool
        self._viewport_width = 0  # type: int
        self._viewport_height = 0  # type: int
        self._window_width = 0  # type: int
        self._window_height = 0  # type: int
        self._auto_adjust_view_port_size = True  # type: bool
        self.setCalculateBoundingBox(False)

    def __deepcopy__(self, memo: Dict[int, object]) -> "Camera":
        copy = cast(Camera, super().__deepcopy__(memo))
        copy._projection_matrix = self._projection_matrix
        copy._window_height = self._window_height
        copy._window_width = self._window_width
        copy._viewport_height = self._viewport_height
        copy._viewport_width = self._viewport_width
        return copy

    def setMeshData(self, mesh_data: Optional["MeshData"]) -> None:
        assert mesh_data is None, "Camera's can't have mesh data"

    def getAutoAdjustViewPort(self) -> bool:
        return self._auto_adjust_view_port_size

    def setAutoAdjustViewPort(self, auto_adjust: bool) -> None:
        self._auto_adjust_view_port_size = auto_adjust

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self) -> Matrix:
        return Matrix(self._projection_matrix.getData())

    def getViewportWidth(self) -> int:
        return self._viewport_width

    def setViewportWidth(self, width: int) -> None:
        self._viewport_width = width

    def setViewPortHeight(self, height: int) -> None:
        self._viewport_height = height

    def setViewportSize(self, width: int, height: int) -> None:
        self._viewport_width = width
        self._viewport_height = height

    def getViewportHeight(self) -> int:
        return self._viewport_height

    def setWindowSize(self, width: int, height: int) -> None:
        self._window_width = width
        self._window_height = height

    def getWindowSize(self) -> Tuple[int, int]:
        return self._window_width, self._window_height

    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix: Matrix) -> None:
        self._projection_matrix = matrix

    def isPerspective(self) -> bool:
        return self._perspective

    def setPerspective(self, perspective: bool) -> None:
        self._perspective = perspective

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x: float, y: float) -> Ray:
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        inverted_projection = numpy.linalg.inv(
            self._projection_matrix.getData().copy())
        transformation = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype=numpy.float32)
        near = numpy.dot(inverted_projection, near)
        near = numpy.dot(transformation, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype=numpy.float32)
        far = numpy.dot(inverted_projection, far)
        far = numpy.dot(transformation, far)
        far = far[0:3] / far[3]

        direction = far - near
        direction /= numpy.linalg.norm(direction)

        return Ray(self.getWorldPosition(),
                   Vector(-direction[0], -direction[1], -direction[2]))

    ##  Project a 3D position onto the 2D view plane.
    def project(self, position: Vector) -> Tuple[float, float]:
        projection = self._projection_matrix
        view = self.getWorldTransformation().getInverse()

        position = position.preMultiply(view)
        position = position.preMultiply(projection)
        return position.x / position.z / 2.0, position.y / position.z / 2.0
예제 #10
0
class Camera(SceneNode.SceneNode):
    def __init__(self, name, parent=None):
        super().__init__(parent)
        self._name = name
        self._projection_matrix = Matrix()
        self._projection_matrix.setOrtho(-5, 5, 5, -5, -100, 100)
        self._perspective = False
        self._viewport_width = 0
        self._viewport_height = 0
        self._window_width = 0
        self._window_height = 0

        self.setCalculateBoundingBox(False)

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self):
        return copy.deepcopy(self._projection_matrix)

    def getViewportWidth(self):
        return self._viewport_width

    def setViewportWidth(self, width):
        self._viewport_width = width

    def setViewPortHeight(self, height):
        self._viewport_height = height

    def setViewportSize(self, width, height):
        self._viewport_width = width
        self._viewport_height = height

    def getViewportHeight(self):
        return self._viewport_height

    def setWindowSize(self, w, h):
        self._window_width = w
        self._window_height = h

    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix):
        self._projection_matrix = matrix

    def isPerspective(self):
        return self._perspective

    def setPerspective(self, pers):
        self._perspective = pers

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x, y):
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        invp = numpy.linalg.inv(self._projection_matrix.getData().copy())
        invv = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype=numpy.float32)
        near = numpy.dot(invp, near)
        near = numpy.dot(invv, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype=numpy.float32)
        far = numpy.dot(invp, far)
        far = numpy.dot(invv, far)
        far = far[0:3] / far[3]

        dir = far - near
        dir /= numpy.linalg.norm(dir)

        return Ray(self.getWorldPosition(), Vector(-dir[0], -dir[1], -dir[2]))

    ##  Project a 3D position onto the 2D view plane.
    def project(self, position):
        projection = self._projection_matrix
        view = self.getWorldTransformation().getInverse()

        position = position.preMultiply(view)
        position = position.preMultiply(projection)

        return (position.x / position.z / 2.0, position.y / position.z / 2.0)
예제 #11
0
파일: Camera.py 프로젝트: Ultimaker/Uranium
class Camera(SceneNode.SceneNode):
    def __init__(self, name: str = "", parent: SceneNode.SceneNode = None) -> None:
        super().__init__(parent)
        self._name = name  # type: str
        self._projection_matrix = Matrix()  # type: Matrix
        self._projection_matrix.setOrtho(-5, 5, 5, -5, -100, 100)
        self._perspective = True  # type: bool
        self._viewport_width = 0  # type: int
        self._viewport_height = 0  # type: int
        self._window_width = 0  # type: int
        self._window_height = 0  # type: int
        self._auto_adjust_view_port_size = True  # type: bool
        self.setCalculateBoundingBox(False)
        self._cached_view_projection_matrix = None # type: Optional[Matrix]

    def __deepcopy__(self, memo: Dict[int, object]) -> "Camera":
        copy = cast(Camera, super().__deepcopy__(memo))
        copy._projection_matrix = self._projection_matrix
        copy._window_height = self._window_height
        copy._window_width = self._window_width
        copy._viewport_height = self._viewport_height
        copy._viewport_width = self._viewport_width
        return copy

    def setMeshData(self, mesh_data: Optional["MeshData"]) -> None:
        assert mesh_data is None, "Camera's can't have mesh data"

    def getAutoAdjustViewPort(self) -> bool:
        return self._auto_adjust_view_port_size

    def setAutoAdjustViewPort(self, auto_adjust: bool) -> None:
        self._auto_adjust_view_port_size = auto_adjust

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self) -> Matrix:
        return self._projection_matrix
    
    def getViewportWidth(self) -> int:
        return self._viewport_width
    
    def setViewportWidth(self, width: int) -> None:
        self._viewport_width = width
    
    def setViewportHeight(self, height: int) -> None:
        self._viewport_height = height
        
    def setViewportSize(self, width: int, height: int) -> None:
        self._viewport_width = width
        self._viewport_height = height

    def getViewProjectionMatrix(self):
        if self._cached_view_projection_matrix is None:
            inverted_transformation = self.getWorldTransformation()
            inverted_transformation.invert()
            self._cached_view_projection_matrix = self._projection_matrix.multiply(inverted_transformation, copy = True)
        return self._cached_view_projection_matrix

    def _updateWorldTransformation(self):
        self._cached_view_projection_matrix = None
        super()._updateWorldTransformation()
    
    def getViewportHeight(self) -> int:
        return self._viewport_height

    def setWindowSize(self, width: int, height: int) -> None:
        self._window_width = width
        self._window_height = height

    def getWindowSize(self) -> Tuple[int, int]:
        return self._window_width, self._window_height

    def render(self, renderer) -> bool:
        # It's a camera. It doesn't need rendering.
        return True
    
    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix: Matrix) -> None:
        self._projection_matrix = matrix
        self._cached_view_projection_matrix = None

    def isPerspective(self) -> bool:
        return self._perspective

    def setPerspective(self, perspective: bool) -> None:
        self._perspective = perspective

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x: float, y: float) -> Ray:
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        inverted_projection = numpy.linalg.inv(self._projection_matrix.getData().copy())
        transformation = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype = numpy.float32)
        near = numpy.dot(inverted_projection, near)
        near = numpy.dot(transformation, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype = numpy.float32)
        far = numpy.dot(inverted_projection, far)
        far = numpy.dot(transformation, far)
        far = far[0:3] / far[3]

        direction = far - near
        direction /= numpy.linalg.norm(direction)

        return Ray(self.getWorldPosition(), Vector(-direction[0], -direction[1], -direction[2]))

    ##  Project a 3D position onto the 2D view plane.
    def project(self, position: Vector) -> Tuple[float, float]:
        projection = self._projection_matrix
        view = self.getWorldTransformation()
        view.invert()

        position = position.preMultiply(view)
        position = position.preMultiply(projection)
        return position.x / position.z / 2.0, position.y / position.z / 2.0
예제 #12
0
파일: Camera.py 프로젝트: derekhe/Uranium
class Camera(SceneNode.SceneNode):
    def __init__(self, name, parent = None):
        super().__init__(parent)
        self._name = name
        self._projection_matrix = Matrix()
        self._projection_matrix.setOrtho(-5, 5, 5, -5, -100, 100)
        self._perspective = False
        self._viewport_width = 0
        self._viewport_height = 0

        self.setCalculateBoundingBox(False)

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self):
        return self._projection_matrix
    
    def getViewportWidth(self):
        return self._viewport_width
    
    def setViewportWidth(self, width):
        self._viewport_width = width
    
    def setViewPortHeight(self,height):
        self._viewport_height = height
        
    def setViewportSize(self,width,height):
        self._viewport_width = width
        self._viewport_height = height
    
    def getViewportHeight(self):
        return self._viewport_height
    
    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix):
        self._projection_matrix = matrix

    def isPerspective(self):
        return self._perspective

    def setPerspective(self, pers):
        self._perspective = pers

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x, y):
        invp = numpy.linalg.inv(self._projection_matrix.getData().copy())
        invv = self.getWorldTransformation().getData()

        near = numpy.array([x, -y, -1.0, 1.0], dtype=numpy.float32)
        near = numpy.dot(invp, near)
        near = numpy.dot(invv, near)
        near = near[0:3] / near[3]

        far = numpy.array([x, -y, 1.0, 1.0], dtype = numpy.float32)
        far = numpy.dot(invp, far)
        far = numpy.dot(invv, far)
        far = far[0:3] / far[3]

        dir = far - near
        dir /= numpy.linalg.norm(dir)

        return Ray(self.getWorldPosition(), Vector(-dir[0], -dir[1], -dir[2]))
예제 #13
0
class Camera(SceneNode.SceneNode):
    def __init__(self, name, parent = None):
        super().__init__(parent)
        self._name = name
        self._projection_matrix = Matrix()
        self._projection_matrix.setOrtho(-5, 5, 5, -5, -100, 100)
        self._perspective = False
        self._viewport_width = 0
        self._viewport_height = 0
        self._window_width = 0
        self._window_height = 0

        self.setCalculateBoundingBox(False)

    ##  Get the projection matrix of this camera.
    def getProjectionMatrix(self):
        return copy.deepcopy(self._projection_matrix)
    
    def getViewportWidth(self):
        return self._viewport_width
    
    def setViewportWidth(self, width):
        self._viewport_width = width
    
    def setViewPortHeight(self,height):
        self._viewport_height = height
        
    def setViewportSize(self,width,height):
        self._viewport_width = width
        self._viewport_height = height
    
    def getViewportHeight(self):
        return self._viewport_height

    def setWindowSize(self, w, h):
        self._window_width = w
        self._window_height = h
    
    ##  Set the projection matrix of this camera.
    #   \param matrix The projection matrix to use for this camera.
    def setProjectionMatrix(self, matrix):
        self._projection_matrix = matrix

    def isPerspective(self):
        return self._perspective

    def setPerspective(self, pers):
        self._perspective = pers

    ##  Get a ray from the camera into the world.
    #
    #   This will create a ray from the camera's origin, passing through (x, y)
    #   on the near plane and continuing based on the projection matrix.
    #
    #   \param x The X coordinate on the near plane this ray should pass through.
    #   \param y The Y coordinate on the near plane this ray should pass through.
    #
    #   \return A Ray object representing a ray from the camera origin through X, Y.
    #
    #   \note The near-plane coordinates should be in normalized form, that is within (-1, 1).
    def getRay(self, x, y):
        window_x = ((x + 1) / 2) * self._window_width
        window_y = ((y + 1) / 2) * self._window_height
        view_x = (window_x / self._viewport_width) * 2 - 1
        view_y = (window_y / self._viewport_height) * 2 - 1

        inverted_projection = numpy.linalg.inv(self._projection_matrix.getData().copy())
        transformation = self.getWorldTransformation().getData()

        near = numpy.array([view_x, -view_y, -1.0, 1.0], dtype = numpy.float32)
        near = numpy.dot(inverted_projection, near)
        near = numpy.dot(transformation, near)
        near = near[0:3] / near[3]

        far = numpy.array([view_x, -view_y, 1.0, 1.0], dtype = numpy.float32)
        far = numpy.dot(inverted_projection, far)
        far = numpy.dot(transformation, far)
        far = far[0:3] / far[3]

        dir = far - near
        dir /= numpy.linalg.norm(dir)

        return Ray(self.getWorldPosition(), Vector(-dir[0], -dir[1], -dir[2]))

    ##  Project a 3D position onto the 2D view plane.
    def project(self, position):
        projection = self._projection_matrix
        view = self.getWorldTransformation().getInverse()

        position = position.preMultiply(view)
        position = position.preMultiply(projection)

        return position.x / position.z / 2.0, position.y / position.z / 2.0