class RootNode(SceneNode): """A special node used as root for the scene tree, which `render()` method renders the entire tree and performs the parent-child transformations chaining. """ def render(self, ctx, transform=None): self.t = Mat() def render_all(node, parent_transform): self.t.identity() self.t *= parent_transform self.t *= node.transform new_t = Mat(self.t) node.render(ctx, new_t) for child in node.children: render_all(child, new_t) for child in self.children: render_all(child, self.transform)
def render(self, ctx, transform=None): self.t = Mat() def render_all(node, parent_transform): self.t.identity() self.t *= parent_transform self.t *= node.transform new_t = Mat(self.t) node.render(ctx, new_t) for child in node.children: render_all(child, new_t) for child in self.children: render_all(child, self.transform)
class Camera(ABC): """Abstract Camera class. A camera abstracts model-view transformations on the scene in a intuitive way, that is, a point in the space (eye) looking at a given point (scene center). """ def __init__(self): self.position = Vec() self.translate_mat = Mat() self.modelview_mat = Mat() self.projection_mat = Mat() def set_position(self, center): """Sets the position of the center of the scene. :param center: The new center of the scene :type center: :class:`matlib.Vec` """ self.position = center self.translate_mat.identity() self.translate_mat.translate(-center) def look_at(self, eye, center, up=None): """Sets up camera look transformation. :param eye: Eye (camera position) coordinates. :type eye: :class:`matlib.Vec` :param eye: Look at (scene center) coordinates. :type eye: :class:`matlib.Vec` :param up: Up vector. :type up: :class:`matlib.Vec` """ up = up or Vec(0, 1, 0) self.modelview_mat.identity() self.modelview_mat.lookat(eye, center, up) def unproject(self, vx, vy, vz, vw, vh): """Unprojects a point in viewport coordinates into world coordinates. :param vx: Viewport X coordinate. :type vx: float :param vy: Viewport Y coordinate. :type vy: float :param vz: Viewport Z coordinate in range [0, 1]. :type vz: float :param vw: Viewport width. :type vw: float :param vh: Viewport height. :type vh: float :returns: Unprojected point in world coordinates. :rtype: :class:`matlib.Vec` """ x_ndc = 2.0 * vx / vw - 1.0 y_ndc = 1.0 - (2.0 * vy) / vh z_ndc = 2 * vz - 1 w_ndc = 1.0 v_clip = Vec(x_ndc, y_ndc, z_ndc, w_ndc) m = self.projection * self.modelview m.invert() out = m * v_clip out.w = 1.0 / out.w out.x *= out.w out.y *= out.w out.z *= out.w return out def trace_ray(self, vx, vy, vw, vh): """Traces a ray from viewport point "into the screen" and returns the ray origin and direction vector. :param vx: Viewport X coordinate. :type vx: float :param vy: Viewport Y coordinate. :type vy: float :param vw: Viewport width. :type vw: float :param vh: Viewport height. :type vh: float :returns: A tuple with the origin being first element and normalized direction vector the second. :rtype: (:class:`matlib.Vec`, :class:`matlib.Vec`) """ p1 = self.unproject(vx, vy, 0, vw, vh) p2 = self.unproject(vx, vy, 1, vw, vh) ray = p2 - p1 ray.norm() return p1, ray @property def modelview(self): """Camera modelview 4x4 matrix.""" return self.modelview_mat * self.translate_mat @property def projection(self): """Camera projection 4x4 matrix.""" return self.projection_mat
def __init__(self): self.position = Vec() self.translate_mat = Mat() self.modelview_mat = Mat() self.projection_mat = Mat()