Exemple #1
0
    def ray_from_ndc(self, pos):
        """Retrieves a ray (origin, direction) corresponding to the given position on screen.
        This function takes the coordinates as NDC (normalized device coordinates), in which the
        lower-left corner of the screen corresponds to (-1,-1) and the upper-right corresponds to
        (1,1).
        For example, to convert mouse coordinates to NDC, you could do something like:

        >>> mouse_pos = pygame.mouse.get_pos()
        >>> mouse_pos = ((mouse_pos[0] / res_x) * 2 - 1, (mouse_pos[1] / res_y) * 2 - 1)
        >>> origin, dir = camera.RayFromNDC(mouse_pos)

        Arguments:
            pos {2-tuple} -- Screen position in NDC (normalized device coordinates)

        Returns:
            Vector3, Vector3 - Origin and direction of the ray corresponding to that screen
            positions
        """

        vpos = Vector3(pos[0], pos[1], self.near_plane)
        vpos.x = vpos.x * self.res_x * 0.5
        vpos.y = -vpos.y * self.res_y * 0.5

        inv_view_proj_matrix = self.get_camera_matrix(
        ) @ self.get_projection_matrix()
        inv_view_proj_matrix = np.linalg.inv(inv_view_proj_matrix)

        direction = inv_view_proj_matrix @ vpos.to_np4(1)
        direction = Vector3.from_np(direction).normalized()

        return self.position + direction * self.near_plane, direction
Exemple #2
0
    def right(self):
        """
        Retrieves the local right vector of this object. The right vector is defined as being
        the x-positive vector multiplied with the local transformation matrix

        Returns:

            {Vector3} - Local right vector of the object
        """
        return Vector3.from_np(Vector3(1, 0, 0).to_np4(0) @ self.get_matrix())
Exemple #3
0
    def forward(self):
        """
        Retrieves the local forward vector of this object. The forward vector is defined as
        being the z-positive vector multiplied with the local transformation matrix

        Returns:

            {Vector3} - Local forward vector of the object
        """
        return Vector3.from_np(Vector3(0, 0, 1).to_np4(0) @ self.get_matrix())
Exemple #4
0
    def get_position(self):
        """
        Retrieves the local position of this object. You can use self.position instead, this
        method actually computes the transfomation matrix and multiplies the 4d vector (0,0,0,1)
        by it. Results should be very similar.

        Returns:

            {Vector3} - Local position of the object
        """
        return Vector3.from_np(Vector3(0, 0, 0).to_np4(1) @ self.get_matrix())
Exemple #5
0
    def __init__(self, name):
        """
        Arguments:

            name {str} -- Name of the object
        """
        self.name = name
        """ {str} Name of the object"""
        self.position = Vector3()
        """ {Vector3} Local position of the object (relative to parent)"""
        self.rotation = quaternion(1, 0, 0, 0)
        """ {quaternion} Local rotation of the object {relative to parent)"""
        self.scale = Vector3(1, 1, 1)
        """ {Vector3} Local scale of the object (relative to parent)"""
        self.mesh = None
        """ {Mesh} Mesh to be rendered in this object"""
        self.material = None
        """ {Material} Material to be used rendering this object"""
        self.children = []
        """ {List[Object3d]} Children objects of this object"""
Exemple #6
0
    def create_cube(size, mesh=None):
        """
        Adds the 6 polygons necessary to form a cube with the given size. If a source mesh is
        not given, a new mesh is created.
        This cube will be centered on the origin (0,0,0).

        Arguments:

            size {3-tuple} -- (x,y,z) size of the cube

            mesh {Mesh} -- Mesh to add the polygons. If not given, create a new mesh

        Returns:
            {Mesh} - Mesh where the polygons were added
        """

        # Create mesh if one was not given
        if mesh is None:
            mesh = Mesh("UnknownCube")

        # Add the 6 quads that create a cube
        Mesh.create_quad(Vector3(size[0] * 0.5, 0, 0),
                         Vector3(0, -size[1] * 0.5, 0),
                         Vector3(0, 0, size[2] * 0.5), mesh)
        Mesh.create_quad(Vector3(-size[0] * 0.5, 0, 0),
                         Vector3(0, size[1] * 0.5, 0),
                         Vector3(0, 0, size[2] * 0.5), mesh)

        Mesh.create_quad(Vector3(0, size[1] * 0.5,
                                 0), Vector3(size[0] * 0.5, 0),
                         Vector3(0, 0, size[2] * 0.5), mesh)
        Mesh.create_quad(Vector3(0, -size[1] * 0.5, 0),
                         Vector3(-size[0] * 0.5, 0),
                         Vector3(0, 0, size[2] * 0.5), mesh)

        Mesh.create_quad(Vector3(0, 0, size[2] * 0.5),
                         Vector3(-size[0] * 0.5, 0),
                         Vector3(0, size[1] * 0.5, 0), mesh)
        Mesh.create_quad(Vector3(0, 0, -size[2] * 0.5),
                         Vector3(size[0] * 0.5, 0),
                         Vector3(0, size[1] * 0.5, 0), mesh)

        return mesh
Exemple #7
0
    def create_sphere(size, res_lat, res_lon, mesh=None):
        """
        Adds the polygons necessary to form a sphere with the given size and resolution.
         If a source mesh is not given, a new mesh is created.
        This sphere will be centered on the origin (0,0,0).

        Arguments:

            size {3-tuple} -- (x,y,z) size of the sphere
            or
            size {number} -- radius of the sphere

            res_lat {int} -- Number of subdivisions in the latitude axis

            res_lon {int} -- Number of subdivisions in the longitudinal axis

            mesh {Mesh} -- Mesh to add the polygons. If not given, create a new mesh

        Returns:
            {Mesh} - Mesh where the polygons were added
        """
        # Create mesh if one was not given
        if mesh is None:
            mesh = Mesh("UnknownSphere")

        # Compute half-size
        if isinstance(size, Vector3):
            hs = size * 0.5
        else:
            hs = Vector3(size[0], size[1], size[2]) * 0.5

        # Sphere is going to be composed by quads in most of the surface, but triangles near the
        # poles, so compute the bottom and top vertex
        bottom_vertex = Vector3(0, -hs.y, 0)
        top_vertex = Vector3(0, hs.y, 0)

        lat_inc = math.pi / res_lat
        lon_inc = math.pi * 2 / res_lon
        # First row of triangles
        lat = -math.pi / 2
        lon = 0

        y = hs.y * math.sin(lat + lat_inc)
        c = math.cos(lat + lat_inc)
        for _ in range(0, res_lon):
            p1 = Vector3(c * math.cos(lon) * hs.x, y, c * math.sin(lon) * hs.z)
            p2 = Vector3(c * math.cos(lon + lon_inc) * hs.x, y,
                         c * math.sin(lon + lon_inc) * hs.z)

            Mesh.create_tri(bottom_vertex, p1, p2, mesh)

            lon += lon_inc

        # Quads in the middle
        for _ in range(1, res_lat - 1):
            lat += lat_inc

            y1 = hs.y * math.sin(lat)
            y2 = hs.y * math.sin(lat + lat_inc)
            c1 = math.cos(lat)
            c2 = math.cos(lat + lat_inc)

            lon = 0
            for _ in range(0, res_lon):
                p1 = Vector3(c1 * math.cos(lon) * hs.x, y1,
                             c1 * math.sin(lon) * hs.z)
                p2 = Vector3(c1 * math.cos(lon + lon_inc) * hs.x, y1,
                             c1 * math.sin(lon + lon_inc) * hs.z)
                p3 = Vector3(c2 * math.cos(lon) * hs.x, y2,
                             c2 * math.sin(lon) * hs.z)
                p4 = Vector3(c2 * math.cos(lon + lon_inc) * hs.x, y2,
                             c2 * math.sin(lon + lon_inc) * hs.z)

                poly = []
                poly.append(p1)
                poly.append(p2)
                poly.append(p4)
                poly.append(p3)

                mesh.polygons.append(poly)

                lon += lon_inc

        # Last row of triangles
        lat += lat_inc
        y = hs.y * math.sin(lat)
        c = math.cos(lat)
        for _ in range(0, res_lon):
            p1 = Vector3(c * math.cos(lon) * hs.x, y, c * math.sin(lon) * hs.z)
            p2 = Vector3(c * math.cos(lon + lon_inc) * hs.x, y,
                         c * math.sin(lon + lon_inc) * hs.z)

            Mesh.create_tri(top_vertex, p1, p2, mesh)

            lon += lon_inc

        return mesh