def draw_axis(self, matrix, length): transform = matrix.decompose() position = transform.translation rotation = transform.rotation axis_x, axis_y, axis_z = rotation.to_axes() head_x = position + axis_x * length head_y = position + axis_y * length head_z = position + axis_z * length red = coloring.RED green = coloring.GREEN blue = coloring.BLUE self.draw_line(position, head_x, red) self.draw_line(position, head_y, green) self.draw_line(position, head_z, blue) self.draw_point(head_x, red) self.draw_point(head_y, green) self.draw_point(head_z, blue) head_radius = length * 0.1 head_height = head_radius * 3.0 head_translate_matrix = Matrix.from_translation( Vector(0.0, length, 0.0)) head_x_rotate_matrix = Matrix.from_angle_axis(-math.pi / 2.0, Vector(0.0, 0.0, 1.0)) self.draw_cone(matrix * head_x_rotate_matrix * head_translate_matrix, head_radius, head_height, red) self.draw_cone(matrix * head_translate_matrix, head_radius, head_height, green) head_z_rotate_matrix = Matrix.from_angle_axis(math.pi / 2.0, Vector(1.0, 0.0, 0.0)) self.draw_cone(matrix * head_z_rotate_matrix * head_translate_matrix, head_radius, head_height, blue)
def computeTransform(self): """Compute final transformation matrix.""" T = self.pos S = self.scale R = self.rot # why have these flags instead of just setting the # values to 0/1? WTF Nintendo. # they seem to only be set when the values already are # 0 (or 1, for scale) anyway. #if self.flags['NO_ROTATION']: R = Vec4(0, 0, 0, 1) #if self.flags['NO_TRANSLATION']: T = Vec3(0, 0, 0) #if self.flags['SCALE_VOL_1']: S = Vec3(1, 1, 1) if self.flags['SEG_SCALE_COMPENSATE']: # apply inverse of parent's scale if self.parent: S *= 1 / self.parent.scale else: log.error("Bone '%s' has flag SEG_SCALE_COMPENSATE but no parent", self.name) # no idea what "scale uniformly" actually means. # XXX billboarding, rigid mtxs, if ever used. # Build matrices from these transformations. print("BONE", self.name) T = Matrix.Translate(4, T) _printMtx(T, 'T') S = Matrix.Scale (4, S) _printMtx(S, 'S') print("R input", R.x, R.y, R.z) R = Quaternion.fromEulerAngles(R).toMatrix() _printMtx(R, 'R') if self.parent: P = self.parent.computeTransform() print("P:",self.parent.pos,self.parent.rot,self.parent.scale) _printMtx(P, 'P:'+self.parent.name) else: P = Matrix.I(4) _printMtx(P, 'P:none') M = Matrix.I(4) #log.debug("Bone '%8s' @ %s R %s: T=\n%srot=\n%s =>\n%s", # self.name, self.pos, self.rot, T, R, R @ T) # multiply by the smooth matrix if any #if self.smooth_mtx_idx >= 0: # mtx = self.fskl.smooth_mtxs[self.smooth_mtx_idx] # # convert 4x3 to 4x4 # mtx = Matrix(mtx[0], mtx[1], mtx[2], (0, 0, 0, 1)) # M = M @ mtx # apply the transformations # SRTP is the order used by BFRES-Viewer... M = M @ S M = M @ R M = M @ T M = M @ P _printMtx(M, 'Final') return M
def update2(self, dt): self.game_time += dt draw = self.app.draw draw.draw_axis(Matrix(), 2.0) draw.draw_grid(1.0, 10, toy.coloring.GRAY) angle = self.game_time q = Quaternion.from_euler_angles(Vector(0.0, angle, 0.0)) R = Matrix.from_rotation(q) S = Matrix.from_scale(Vector(4.0, 1.0, 1.0)) draw.draw_box(R * S, toy.coloring.GREEN) draw.draw_box(S * R, toy.coloring.YELLOW)
def read(self, buffer, offset): d = struct.unpack_from('9d', buffer, offset) return Matrix( d[0:3], d[3:6], d[6:9], )
def read(self, buffer, offset): d = struct.unpack_from('12d', buffer, offset) return Matrix( d[0:4], d[4:8], d[8:12], )
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 __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 _readSmoothMtxs(self, fres): """Read the smooth matrices.""" self.smooth_mtxs = [] for i in range(max(self.smooth_idxs)): mtx = fres.read('3f', count=4, pos=self.smooth_mtx_offs + (i * 16 * 3)) # warn about invalid values for y in range(4): for x in range(3): n = mtx[y][x] if math.isnan(n) or math.isinf(n): log.warning( "Skeleton smooth mtx %d element [%d,%d] is %s", i, x, y, n) # replace all invalid values with zeros flt = lambda e: \ 0 if (math.isnan(e) or math.isinf(e)) else e mtx = list(map(lambda row: list(map(flt, row)), mtx)) #mtx[3][3] = 1 # debug mtx = Matrix(*mtx) # transpose #m = [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]] #for y in range(4): # for x in range(4): # m[x][y] = mtx[y][x] #mtx = m # log values to debug #log.debug("Inverse mtx %d:", i) #for y in range(4): # log.debug(" %s", ' '.join(map( # lambda v: '%+3.2f' % v, mtx[y]))) self.smooth_mtxs.append(mtx)
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 set_perspective(self, fov): self.perspective_fov = fov self.projection_perspective = Matrix.from_perspective( fov, self.aspect, 0.1, 1000.0)
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 update3(self, dt): # print('game_time', id(self), self.game_time) self.game_time += dt draw = self.app.draw draw.draw_axis(Matrix(), 10.0) draw.draw_grid(10.0, 5, toy.coloring.LIGHT_GRAY) draw.draw_grid(1.0, 10, toy.coloring.GRAY) camera = self.app.camera p = camera.top_down_screen_to_world( Vector(camera.width / 2.0, camera.height / 2.0, 0.0)) draw.draw_sphere(p, 1.0, toy.coloring.RED) p = camera.top_down_screen_to_world(Vector(0.0, 0.0, 0.0)) draw.draw_sphere(p, 1.0, toy.coloring.GREEN) p = camera.top_down_screen_to_world( Vector(camera.width, camera.height, 0.0)) draw.draw_sphere(p, 1.0, toy.coloring.BLUE) model_matrix = Transform( # Vector(5.0*math.cos(self.game_time), 0.0, 5.0*math.sin(self.game_time)), # Quaternion.from_euler_angles(Vector(self.game_time * 3.0, self.game_time, 0.0)) ).to_matrix() sub_model_matrix = Transform(Vector(0.0, 2.0 * self.game_time, 0.0)).to_matrix() draw = toy.draw.LocalDraw(self.app.batch, model_matrix) sub_draw = toy.draw.LocalDraw(self.app.batch, model_matrix * sub_model_matrix) sub_draw.draw_sphere(Vector(0.0, 0.0, 0.0), 5.0, toy.coloring.MAGENTA) draw.draw_point(Vector(0.0, 2.0, 0.0)) draw.draw_line(Vector(-5.0, 1.0, 0.0), Vector(5.0, 1.0, 0.0)) draw.draw_sphere(Vector(0.0, 3.0, 0.0), 2.0, toy.coloring.BLUE) transform = Transform( Vector(1.0, 2.0, 4.0), Quaternion.from_euler_angles(Vector(0.8, 0.2, 0.0))) matrix = transform.to_matrix() draw.draw_cone(matrix, 1.0, 2.0) draw.draw_axis(matrix, 1.0) draw.draw_cube(Vector(), 1.0) draw.draw_box(matrix, toy.coloring.GREEN) p0 = Vector(0.0, 100.0, 0.0) p1 = Vector(3.0, 6.0, 9.0) draw.draw_line(p0, p1, toy.coloring.CYAN) draw.draw_cylinder(p0, p1, 1.0) p0 = Vector(0.0, 10.0, 0.0) p1 = 30.0 * Vector(math.cos(self.game_time), math.sin(self.game_time), 1.0) draw.draw_cylinder(p0, p1, 3.0) draw.draw_sphere(p1, 3.0, toy.coloring.CYAN) points = [] for i in range(50): r = i * 0.5 a = r + self.game_time points.append(Vector(math.cos(a), r, math.sin(a))) draw.draw_polyline(points, toy.coloring.CYAN) text_batch = self.app.text_batch text_batch.draw_text(Vector(0.0, 0.0, 0.0), 'abcabfdsfdc') text_batch.draw_text(Vector(0.0, 20.0, 0.0), 'defdef', toy.coloring.MAGENTA) text_batch.draw_text(Vector(0.0, 200.0, 0.0), 'ABCABC\nDEFDEF') text_batch.draw_text(Vector(0.0, 500.0, 0.0), '1234567890', toy.coloring.BLUE, 2.0) view_eye = self.app.camera.view_eye view_at = self.app.camera.view_at view_info = 'eye {}, dir {}'.format(view_eye, view_at - view_eye) text_batch.draw_text(Vector(10.0, 400.0, 0.0), view_info, toy.coloring.BLACK, 0.4) world_p = (model_matrix * sub_model_matrix).transform_point( Vector(0.0, 0.0, 0.0)) # world_p = Vector() screen_p = camera.world_to_screen(world_p) text_batch.draw_text(screen_p, 'Lklm world{}'.format(world_p), toy.coloring.BLACK, 0.5) model_matrix = Transform( Vector(), Quaternion.from_euler_angles(Vector(0.0, 0.0 * self.game_time, 0.0)), Vector(1.0, 1.0, 1.0) * 1.0).to_matrix()