Module pyxyz.object3d

3d Object class

Expand source code
"""3d Object class"""

import numpy as np
from quaternion import quaternion, as_rotation_matrix
from pyxyz.vector3 import Vector3

class Object3d:
    """3d object class.
    This is the base class of all objects added to the scene graph.
    """
    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"""

    def get_matrix(self):
        """
        Retrieves the local transformation matrix of this object

        Returns:

            {np.array} -- Local transformation matrix
        """
        return Object3d.get_prs_matrix(self.position, self.rotation, self.scale)

    def render(self, screen, clip_matrix):
        """
        Renders this object with the given clip_matrix.

        Arguments:

            screen {pygame.Surface} -- Pygame surface in which this object will be rendered

            clip_matrix {np.array} -- Parent transformation matrix (including view and projection
            matrix)
        """

        # Retrieve the local transformation matrix
        world_matrix = self.get_matrix()

        # Multiply the local transformation with the clip matrix (transformation compositing)
        mesh_matrix = world_matrix @ clip_matrix

        # If there's a mesh and a material
        if ((self.material is not None) and (self.mesh is not None)):
            self.mesh.render(screen, mesh_matrix, self.material)

        # Traverse the children of this object, rendering them
        for child in self.children:
            child.render(screen, mesh_matrix)

    def add_child(self, obj):
        """
        Adds a child object to the hierarchy of this one

        Arguments:

            obj {Object3d} -- Object to add to the hierarchy
        """
        self.children.append(obj)

    def remove_child(self, obj):
        """
        Removes a child object from the hierarchy of this one. If the object isn't a child of
        this one, nothing happens

        Arguments:

            obj {Object3d} -- Object to remove from the hierarchy
        """
        if obj in self.children:
            self.children.remove(obj)

    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())

    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())

    def up(self):
        """
        Retrieves the local up vector of this object. The up vector is defined as being
        the y-positive vector multiplied with the local transformation matrix

        Returns:

            {Vector3} - Local up vector of the object
        """
        return Vector3.from_np(Vector3(0, 1, 0).to_np4(0) @ self.get_matrix())

    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())

    @staticmethod
    def get_prs_matrix(position, rotation, scale):
        """
        Creates a PRS matrix from the given position, rotation and scale

        Arguments:

            position {Vector3} - Position

            rotation {quaternion} - Rotation

            scale {Vector3} - Scale

        Returns:

            {np.array} - PRS matrix
        """
        trans = np.identity(4)
        trans[3][0] = position.x
        trans[3][1] = position.y
        trans[3][2] = position.z

        qrot = as_rotation_matrix(rotation)
        rotation_matrix = np.identity(4)
        rotation_matrix[0][0] = qrot[0][0]
        rotation_matrix[0][1] = qrot[0][1]
        rotation_matrix[0][2] = qrot[0][2]
        rotation_matrix[1][0] = qrot[1][0]
        rotation_matrix[1][1] = qrot[1][1]
        rotation_matrix[1][2] = qrot[1][2]
        rotation_matrix[2][0] = qrot[2][0]
        rotation_matrix[2][1] = qrot[2][1]
        rotation_matrix[2][2] = qrot[2][2]
        rotation_matrix[3][3] = 1

        scale_matrix = np.identity(4)
        scale_matrix[0][0] = scale.x
        scale_matrix[1][1] = scale.y
        scale_matrix[2][2] = scale.z

        return scale_matrix @ rotation_matrix @ trans

Classes

class Object3d (name)

3d object class. This is the base class of all objects added to the scene graph.

Arguments

name {str} – Name of the object

Expand source code
class Object3d:
    """3d object class.
    This is the base class of all objects added to the scene graph.
    """
    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"""

    def get_matrix(self):
        """
        Retrieves the local transformation matrix of this object

        Returns:

            {np.array} -- Local transformation matrix
        """
        return Object3d.get_prs_matrix(self.position, self.rotation, self.scale)

    def render(self, screen, clip_matrix):
        """
        Renders this object with the given clip_matrix.

        Arguments:

            screen {pygame.Surface} -- Pygame surface in which this object will be rendered

            clip_matrix {np.array} -- Parent transformation matrix (including view and projection
            matrix)
        """

        # Retrieve the local transformation matrix
        world_matrix = self.get_matrix()

        # Multiply the local transformation with the clip matrix (transformation compositing)
        mesh_matrix = world_matrix @ clip_matrix

        # If there's a mesh and a material
        if ((self.material is not None) and (self.mesh is not None)):
            self.mesh.render(screen, mesh_matrix, self.material)

        # Traverse the children of this object, rendering them
        for child in self.children:
            child.render(screen, mesh_matrix)

    def add_child(self, obj):
        """
        Adds a child object to the hierarchy of this one

        Arguments:

            obj {Object3d} -- Object to add to the hierarchy
        """
        self.children.append(obj)

    def remove_child(self, obj):
        """
        Removes a child object from the hierarchy of this one. If the object isn't a child of
        this one, nothing happens

        Arguments:

            obj {Object3d} -- Object to remove from the hierarchy
        """
        if obj in self.children:
            self.children.remove(obj)

    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())

    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())

    def up(self):
        """
        Retrieves the local up vector of this object. The up vector is defined as being
        the y-positive vector multiplied with the local transformation matrix

        Returns:

            {Vector3} - Local up vector of the object
        """
        return Vector3.from_np(Vector3(0, 1, 0).to_np4(0) @ self.get_matrix())

    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())

    @staticmethod
    def get_prs_matrix(position, rotation, scale):
        """
        Creates a PRS matrix from the given position, rotation and scale

        Arguments:

            position {Vector3} - Position

            rotation {quaternion} - Rotation

            scale {Vector3} - Scale

        Returns:

            {np.array} - PRS matrix
        """
        trans = np.identity(4)
        trans[3][0] = position.x
        trans[3][1] = position.y
        trans[3][2] = position.z

        qrot = as_rotation_matrix(rotation)
        rotation_matrix = np.identity(4)
        rotation_matrix[0][0] = qrot[0][0]
        rotation_matrix[0][1] = qrot[0][1]
        rotation_matrix[0][2] = qrot[0][2]
        rotation_matrix[1][0] = qrot[1][0]
        rotation_matrix[1][1] = qrot[1][1]
        rotation_matrix[1][2] = qrot[1][2]
        rotation_matrix[2][0] = qrot[2][0]
        rotation_matrix[2][1] = qrot[2][1]
        rotation_matrix[2][2] = qrot[2][2]
        rotation_matrix[3][3] = 1

        scale_matrix = np.identity(4)
        scale_matrix[0][0] = scale.x
        scale_matrix[1][1] = scale.y
        scale_matrix[2][2] = scale.z

        return scale_matrix @ rotation_matrix @ trans

Subclasses

Static methods

def get_prs_matrix(position, rotation, scale)

Creates a PRS matrix from the given position, rotation and scale

Arguments

position {Vector3} - Position

rotation {quaternion} - Rotation

scale {Vector3} - Scale

Returns

{np.array} - PRS matrix

Expand source code
@staticmethod
def get_prs_matrix(position, rotation, scale):
    """
    Creates a PRS matrix from the given position, rotation and scale

    Arguments:

        position {Vector3} - Position

        rotation {quaternion} - Rotation

        scale {Vector3} - Scale

    Returns:

        {np.array} - PRS matrix
    """
    trans = np.identity(4)
    trans[3][0] = position.x
    trans[3][1] = position.y
    trans[3][2] = position.z

    qrot = as_rotation_matrix(rotation)
    rotation_matrix = np.identity(4)
    rotation_matrix[0][0] = qrot[0][0]
    rotation_matrix[0][1] = qrot[0][1]
    rotation_matrix[0][2] = qrot[0][2]
    rotation_matrix[1][0] = qrot[1][0]
    rotation_matrix[1][1] = qrot[1][1]
    rotation_matrix[1][2] = qrot[1][2]
    rotation_matrix[2][0] = qrot[2][0]
    rotation_matrix[2][1] = qrot[2][1]
    rotation_matrix[2][2] = qrot[2][2]
    rotation_matrix[3][3] = 1

    scale_matrix = np.identity(4)
    scale_matrix[0][0] = scale.x
    scale_matrix[1][1] = scale.y
    scale_matrix[2][2] = scale.z

    return scale_matrix @ rotation_matrix @ trans

Instance variables

var children

{List[Object3d]} Children objects of this object

var material

{Material} Material to be used rendering this object

var mesh

{Mesh} Mesh to be rendered in this object

var name

{str} Name of the object

var position

{Vector3} Local position of the object (relative to parent)

var rotation

{quaternion} Local rotation of the object {relative to parent)

var scale

{Vector3} Local scale of the object (relative to parent)

Methods

def add_child(self, obj)

Adds a child object to the hierarchy of this one

Arguments

obj {Object3d} – Object to add to the hierarchy

Expand source code
def add_child(self, obj):
    """
    Adds a child object to the hierarchy of this one

    Arguments:

        obj {Object3d} -- Object to add to the hierarchy
    """
    self.children.append(obj)
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

Expand source code
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())
def get_matrix(self)

Retrieves the local transformation matrix of this object

Returns

{np.array} – Local transformation matrix

Expand source code
def get_matrix(self):
    """
    Retrieves the local transformation matrix of this object

    Returns:

        {np.array} -- Local transformation matrix
    """
    return Object3d.get_prs_matrix(self.position, self.rotation, self.scale)
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

Expand source code
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())
def remove_child(self, obj)

Removes a child object from the hierarchy of this one. If the object isn't a child of this one, nothing happens

Arguments

obj {Object3d} – Object to remove from the hierarchy

Expand source code
def remove_child(self, obj):
    """
    Removes a child object from the hierarchy of this one. If the object isn't a child of
    this one, nothing happens

    Arguments:

        obj {Object3d} -- Object to remove from the hierarchy
    """
    if obj in self.children:
        self.children.remove(obj)
def render(self, screen, clip_matrix)

Renders this object with the given clip_matrix.

Arguments

screen {pygame.Surface} – Pygame surface in which this object will be rendered

clip_matrix {np.array} – Parent transformation matrix (including view and projection matrix)

Expand source code
def render(self, screen, clip_matrix):
    """
    Renders this object with the given clip_matrix.

    Arguments:

        screen {pygame.Surface} -- Pygame surface in which this object will be rendered

        clip_matrix {np.array} -- Parent transformation matrix (including view and projection
        matrix)
    """

    # Retrieve the local transformation matrix
    world_matrix = self.get_matrix()

    # Multiply the local transformation with the clip matrix (transformation compositing)
    mesh_matrix = world_matrix @ clip_matrix

    # If there's a mesh and a material
    if ((self.material is not None) and (self.mesh is not None)):
        self.mesh.render(screen, mesh_matrix, self.material)

    # Traverse the children of this object, rendering them
    for child in self.children:
        child.render(screen, mesh_matrix)
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

Expand source code
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())
def up(self)

Retrieves the local up vector of this object. The up vector is defined as being the y-positive vector multiplied with the local transformation matrix

Returns

{Vector3} - Local up vector of the object

Expand source code
def up(self):
    """
    Retrieves the local up vector of this object. The up vector is defined as being
    the y-positive vector multiplied with the local transformation matrix

    Returns:

        {Vector3} - Local up vector of the object
    """
    return Vector3.from_np(Vector3(0, 1, 0).to_np4(0) @ self.get_matrix())