class Actor(object): def __init__(self, world, actor_id, param): self.world = world self.actor_id = actor_id self._position = Vector() if 'position' in param: self._position = param['position'] def update(self, delta_time): pass def on_destroy(self): pass def get_position(self): return self._position.copy() def set_position(self, position): self._position = position.copy()
class Camera(object): MODE_PERSPECTIVE = 1 MODE_ORTHO = 2 def __init__(self): self.width = 512 self.height = 512 self.aspect = 1.0 self.view = Matrix() self.perspective_fov = math.radians(60.0) self.ortho_extent = 10.0 self.view_eye = Vector(0.0, 4.0, -10.0) self.view_at = Vector(0.0, 0.0, 0.0) self.view_up = Vector(0.0, 1.0, 0.0) self.set_look_at(self.view_eye, self.view_at, self.view_up) self.set_perspective(self.perspective_fov) self.set_ortho(self.ortho_extent) self.mode = self.MODE_PERSPECTIVE def set_new_size(self, width, height): self.width = width self.height = height self.aspect = width / height self.set_perspective(self.perspective_fov) self.set_ortho(self.ortho_extent) def set_mode(self, mode): self.mode = mode def get_look_at(self): return (self.view_eye.copy(), self.view_at.copy(), self.view_up.copy()) def set_look_at(self, eye, at, up): self.view_eye = eye self.view_at = at self.view_up = up self.view = Matrix.from_look_at(eye, at, up) def set_perspective(self, fov): self.perspective_fov = fov self.projection_perspective = Matrix.from_perspective( fov, self.aspect, 0.1, 1000.0) def set_ortho(self, extent): design_height = 600 self.ortho_extent = extent left = -extent * self.aspect right = extent * self.aspect top = extent bottom = -extent near = 0.0 far = 1000.0 self.projection_ortho = Matrix.from_ortho(left, right, bottom, top, near, far) def get_projection(self): _mode = self.mode if _mode == self.MODE_PERSPECTIVE: return self.projection_perspective elif _mode == self.MODE_ORTHO: return self.projection_ortho else: return self.projection_perspective def get_view_projection(self): return self.get_projection() * self.view def get_screen_view_projection(self): design_height = 600 height = design_height width = design_height * self.aspect return Matrix.from_ortho(0.0, width, 0.0, height, -1.0, 1.0) def world_to_screen(self, position): vp_matrix = self.get_view_projection() clip_position = vp_matrix.project_point(position) height = 600 width = height * self.aspect return Vector((clip_position.x + 1.0) * width / 2.0, (clip_position.y + 1.0) * height / 2.0, 1.0 - clip_position.z) def top_down_screen_to_world(self, position): screen_x = position.x screen_y = self.height - position.y clip_x = (screen_x - self.width / 2.0) * 2.0 / self.width clip_y = (screen_y - self.height / 2.0) * 2.0 / self.height pmatrix = self.projection_ortho world_origin_x = (clip_x + pmatrix.m30) / pmatrix.m00 world_origin_y = (clip_y + pmatrix.m31) / pmatrix.m11 world_x = self.view_eye.x - world_origin_x world_z = self.view_eye.z - world_origin_y return Vector(world_x, 0.0, world_z) def screen_to_ray(self, position): pass