def find_projected_arc_center(p1, p2, b, radius=0.5): """ . . B. . . c. .a . . . C . = 90 .....A........b.......... c = circle enter distance b = tangent distance """ a = Vector(p1) b = Vector(b) c = Vector(p2) a = (a - b).normalized() + b c = (c - b).normalized() + b focal = (a + c) / 2.0 focal_length = (b - focal).length try: angleA = (a - b).angle(c - b) / 2.0 except ValueError as e: print('smoothlines encountered non zero length vectors') # Vector.angle(other): zero length vectors have no valid angle return None # slightly undefined input handled ugly-er try: sideA = radius sideB = sideA / tan(angleA) sideC = sideA / sin(angleA) except Exception as e: print(e) print( "no idea why this input happens.. show me a shorter version of your input mesh" ) return None try: ratio = (sideC - radius) / focal_length except Exception as e: print(e) print("smoothlines encountered two colinear lines, no arc to generate") # this will be interpreted as a no-op # potentially here you could return something like [lerp(A,B, "radius"), B, lerp(C, B, "radius")] return None mid = b.lerp(focal, ratio)[:] ab_rate = sideB / (a - b).length cb_rate = sideB / (c - b).length p1 = b.lerp(a, ab_rate)[:] p2 = b.lerp(c, cb_rate)[:] return p1, mid, p2
def addFaces(self, fType=None): Ya = self.Ya Xb = self.Xb Xc = self.Xc if (self.triangleFace == 'DEFAULT'): self.Faces = [[0, 1, 2]] return True if (self.triangleFace == 'TRIANGLES'): A = Vector([0.0, Ya, 0.0]) B = Vector([Xb, 0.0, 0.0]) C = Vector([Xc, 0.0, 0.0]) D = Vector([((A.x + B.x + C.x) / 3), ((A.y + B.y + C.y) / 3), ((A.z + B.z + C.z) / 3)]) self.Vertices = [A, B, C, D, ] self.Faces = [[0, 1, 3], [1, 2, 3], [2, 0, 3]] return True if (self.triangleFace == 'QUADS'): A = Vector([0.0, Ya, 0.0]) B = Vector([Xb, 0.0, 0.0]) C = Vector([Xc, 0.0, 0.0]) D = Vector([((A.x + B.x + C.x) / 3), ((A.y + B.y + C.y) / 3), ((A.z + B.z + C.z) / 3)]) AB = A.lerp(B, 0.5) AC = A.lerp(C, 0.5) BC = B.lerp(C, 0.5) self.Vertices = [A, AB, B, BC, C, AC, D, ] self.Faces = [[0, 1, 6, 5], [1, 2, 3, 6], [3, 4, 5, 6]] return True if (self.triangleFace == 'SAFEQUADS'): A = Vector([0.0, Ya, 0.0]) B = Vector([Xb, 0.0, 0.0]) C = Vector([Xc, 0.0, 0.0]) D = Vector([((A.x + B.x + C.x) / 3), ((A.y + B.y + C.y) / 3), ((A.z + B.z + C.z) / 3)]) E = A.lerp(D, 0.5) AB = A.lerp(B, 0.5) AC = A.lerp(C, 0.5) BC = B.lerp(C, 0.5) AAB = AB.lerp(A, 0.5) AAC = AC.lerp(A, 0.5) BBA = AB.lerp(B, 0.5) BBC = BC.lerp(B, 0.5) BCC = BC.lerp(C, 0.5) CCA = AC.lerp(C, 0.5) self.Vertices = [A, AAB, BBA, B, BBC, BC, BCC, C, CCA, AAC, D, E, ] self.Faces = [[0, 1, 11, 9], [1, 2, 10, 11], [2, 3, 4, 10], [4, 5, 6, 10], [6, 7, 8, 10], [8, 9, 11, 10]] return True return False
def execute(self, context): tracks = self._tracks(context) track = tracks.active first_frame = min(m.frame for m in track.markers) for corner_index in range(4): new_track = self._new_track(tracks, '%s.%s' % (track.name, corner_index), first_frame) for marker in track.markers: corner = Vector(marker.pattern_corners[corner_index]) self._new_offset_marker(marker, corner, new_track) print("added new track %s" % new_track.name) if self.dense_fill: for c1, c2 in [(0, 1), (1, 2), (2, 3), (3, 0)]: new_track = self._new_track(tracks, '%s.%s-%s' % (track.name, c1, c2), first_frame) for marker in track.markers: corner1 = Vector(marker.pattern_corners[c1]) corner2 = Vector(marker.pattern_corners[c2]) self._new_offset_marker(marker, corner1.lerp(corner2, .5), new_track) print("added new dense track %s" % new_track.name) return {'FINISHED'}
def do_update_heat_map(node_list, nodes): """ Create a heat map for the node tree, Needs development. """ if not nodes.id_data.sv_user_colors: color_data = { node.name: (node.color[:], node.use_custom_color) for node in nodes } nodes.id_data.sv_user_colors = str(color_data) times = do_update_general(node_list, nodes) if not times: return t_max = max(times) addon_name = data_structure.SVERCHOK_NAME addon = bpy.context.user_preferences.addons.get(addon_name) if addon: # to use Vector.lerp cold = Vector(addon.preferences.heat_map_cold) hot = addon.preferences.heat_map_hot else: print("Cannot find preferences") cold = Vector((1, 1, 1)) hot = (.8, 0, 0) for name, t in zip(node_list, times): nodes[name].use_custom_color = True # linear scale. nodes[name].color = cold.lerp(hot, t / t_max)
def render(self): diameter = 4.0 sz = 2.125 / diameter base_object = helpers.infer_primitive(random.choice(self.PRIMITIVES), location=(100, 100, 100), radius=sz) latitude = 16 longitude = latitude * 2 invlatitude = 1.0 / (latitude - 1) invlongitude = 1.0 / (longitude - 1) iprc = 0.0 jprc = 0.0 phi = 0.0 theta = 0.0 invfcount = 1.0 / (self.NUMBER_OF_FRAMES - 1) # Animate center of the sphere. center = Vector((0.0, 0.0, 0.0)) startcenter = Vector((0.0, -4.0, 0.0)) stopcenter = Vector((0.0, 4.0, 0.0)) # Rotate cubes around the surface of the sphere. pt = Vector((0.0, 0.0, 0.0)) rotpt = Vector((0.0, 0.0, 0.0)) # Change the axis of rotation for the point. baseaxis = Vector((0.0, 1.0, 0.0)) axis = Vector((0.0, 0.0, 0.0)) # Slerp between two rotations for each cube. startrot = Quaternion((0.0, 1.0, 0.0), pi) stoprot = Quaternion((1.0, 0.0, 0.0), pi * 1.5) currot = Quaternion() for i in range(0, latitude, 1): iprc = i * invlatitude phi = pi * (i + 1) * invlatitude rad = 0.01 + sz * abs(sin(phi)) * 0.99 pt.z = cos(phi) * diameter for j in range(0, longitude, 1): jprc = j * invlongitude theta = TWOPI * j / longitude pt.y = center.y + sin(phi) * sin(theta) * diameter pt.x = center.x + sin(phi) * cos(theta) * diameter current = helpers.duplicate_object(base_object) current.location = pt current.name = 'Object ({0:0>2d}, {1:0>2d})'.format(i, j) current.data.name = 'Mesh ({0:0>2d}, {1:0>2d})'.format(i, j) current.rotation_euler = (0.0, phi, theta) helpers.assign_material( current, helpers.random_material(self.MATERIALS_NAMES)) axis = self.vecrotatex(theta, baseaxis) currot = startrot center = startcenter for f in range(0, self.NUMBER_OF_FRAMES, 1): fprc = f / (self.NUMBER_OF_FRAMES - 1) osc = abs(sin(TWOPI * fprc)) bpy.context.scene.frame_set(f) center = startcenter.lerp(stopcenter, osc) current.location = helpers.rotate_vector( TWOPI * fprc, axis, pt) current.keyframe_insert(data_path='location') currot = startrot.slerp(stoprot, jprc * fprc) current.rotation_euler = currot.to_euler() current.keyframe_insert(data_path='rotation_euler')
def do_update_heat_map(node_list, nodes): """ Create a heat map for the node tree, Needs development. """ if not nodes.id_data.sv_user_colors: color_data = {node.name: (node.color[:], node.use_custom_color) for node in nodes} nodes.id_data.sv_user_colors = str(color_data) times = do_update_general(node_list, nodes) if not times: return t_max = max(times) addon_name = data_structure.SVERCHOK_NAME addon = bpy.context.user_preferences.addons.get(addon_name) if addon: # to use Vector.lerp cold = Vector(addon.preferences.heat_map_cold) hot = addon.preferences.heat_map_hot else: error("Cannot find preferences") cold = Vector((1, 1, 1)) hot = (.8, 0, 0) for name, t in zip(node_list, times): nodes[name].use_custom_color = True # linear scale. nodes[name].color = cold.lerp(hot, t / t_max)
def split_segment(keyframes, type1, start, end, tolerance): n = float(end[0] - start[0]) error = -1 frame = 0 # print('Start: %d, End: %d, Range: %f' % (start[0], end[0], n)) for i in (i for i in range(start[0], end[0]) if i in keyframes.keys()): middle = keyframes[i] distance = 0 t = max(0, min(1, float(i - start[0]) / n)) # Interpolation factor if type1 == 'Translation' or type1 == 'Scale': a = Vector(start[1]) b = Vector(middle) c = Vector(end[1]) delta = b - a.lerp(c, t) distance = delta.magnitude # Just the linear distance, for now elif type1 == 'Rotation': distance = 1 - Quaternion(middle).dot( Quaternion(start[1]).slerp(Quaternion( end[1]), t)) # Spherical distance in the range of 0-2 if distance > error: error = distance frame = i if error > 0 and error > tolerance: middle = (frame, keyframes[frame]) result = [middle] if frame != start[0] and frame != end[0]: # Prevents infinite recursion result += split_segment(keyframes, type1, start, middle, tolerance) result += split_segment(keyframes, type1, middle, end, tolerance) return result return []
def execute(self, context): expr = self.expr obs = list(context.selected_objects) tot = len(obs) - 1 inc = 1 / tot first, last = obs[0], obs[-1] obj1, prop1 = propexpr(first, expr) obj2, prop2 = propexpr(last, expr) attr1 = getattr(obj1, prop1) attr2 = getattr(obj2, prop2) if isinstance(attr1, Vector): for n, ob in enumerate(obs[1:-1]): fac = inc * (n + 1) objx, propx = propexpr(ob, expr) attrx = getattr(objx, propx) attrx[:] = attr1.lerp(attr2, fac) elif isinstance(attr1, Color): r1, g1, b1 = attr1 r2, g2, b2 = attr2 vec1 = Vector((r1, g1, b1)) vec2 = Vector((r2, g2, b2)) for n, ob in enumerate(obs[1:-1]): fac = inc * (n + 1) objx, propx = propexpr(ob, expr) attrx = getattr(objx, propx) attrx[:] = vec1.lerp(vec2, fac) elif isinstance(attr1, bpy.types.bpy_prop_array) and len(attr1) == 4: r1, g1, b1, a1 = attr1 r2, g2, b2, a2 = attr2 vec1 = Vector((r1, g1, b1)) vec2 = Vector((r2, g2, b2)) avec1 = Vector((a1, a1, a1)) avec2 = Vector((a2, a2, a2)) for n, ob in enumerate(obs[1:-1]): fac = inc * (n + 1) objx, propx = propexpr(ob, expr) attrx = getattr(objx, propx) t = (*vec1.lerp(vec2, fac), avec1.lerp(avec2, fac)[0]) attrx[:] = t elif type(attr1) == float: for n, ob in enumerate(obs[1:-1]): fac = inc * (n + 1) v1 = Vector((attr1, ) * 3) v2 = Vector((attr2, ) * 3) objx, propx = propexpr(ob, expr) setattr(objx, propx, v1.lerp(v2, fac)[0]) return {"FINISHED"}
def makecube(self, size, divx, divy, divz): if 0 in (divx, divy, divz): return [], [] b = size / 2.0 verts = [ [b, b, -b], [b, -b, -b], [-b, -b, -b], [-b, b, -b], [b, b, b], [b, -b, b], [-b, -b, b], [-b, b, b] ] faces = [[0, 1, 2, 3], [4, 7, 6, 5], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [4, 0, 3, 7]] if (divx, divy, divz) == (1, 1, 1): return verts, faces bm = bmesh.new() [bm.verts.new(co) for co in verts] bm.verts.index_update() for face in faces: bm.faces.new(tuple(bm.verts[i] for i in face)) bm.faces.index_update() dist = 0.0001 section_dict = {0: divx, 1: divy, 2: divz} for axis in range(3): num_sections = section_dict[axis] if num_sections == 1: continue step = 1 / num_sections v1 = Vector(tuple((b if (i == axis) else 0) for i in [0, 1, 2])) v2 = Vector(tuple((-b if (i == axis) else 0) for i in [0, 1, 2])) for section in range(num_sections): mid_vec = v1.lerp(v2, section * step) plane_no = v2 - mid_vec plane_co = mid_vec visible_geom = bm.faces[:] + bm.verts[:] + bm.edges[:] bmesh.ops.bisect_plane( bm, geom=visible_geom, dist=dist, plane_co=plane_co, plane_no=plane_no, use_snap_center=False, clear_outer=False, clear_inner=False) indices = lambda i: [j.index for j in i.verts] verts = [v.co.to_tuple() for v in bm.verts] faces = [indices(face) for face in bm.faces] edges = [indices(edge) for edge in bm.edges] return [verts], edges, [faces]
def find_projected_arc_center(p1, p2, b, radius=0.5): """ . . B. . . c. .a . . . C . = 90 .....A........b.......... c = circle enter distance b = tangent distance """ a = Vector(p1) b = Vector(b) c = Vector(p2) a = (a - b).normalized() + b c = (c - b).normalized() + b focal = (a + c) / 2.0 focal_length = (b - focal).length try: angleA = (a - b).angle(c - b) / 2.0 except ValueError as e: print('smoothlines encountered non zero length vectors') # Vector.angle(other): zero length vectors have no valid angle return None sideA = radius sideB = sideA / tan(angleA) sideC = sideA / sin(angleA) ratio = (sideC - radius) / focal_length mid = b.lerp(focal, ratio)[:] ab_rate = sideB / (a - b).length cb_rate = sideB / (c - b).length p1 = b.lerp(a, ab_rate)[:] p2 = b.lerp(c, cb_rate)[:] return p1, mid, p2
def makecube(self, size, divx, divy, divz): if 0 in (divx, divy, divz): return [], [] b = size / 2.0 verts = [[b, b, -b], [b, -b, -b], [-b, -b, -b], [-b, b, -b], [b, b, b], [b, -b, b], [-b, -b, b], [-b, b, b]] faces = [[0, 1, 2, 3], [4, 7, 6, 5], [0, 4, 5, 1], [1, 5, 6, 2], [2, 6, 7, 3], [4, 0, 3, 7]] if (divx, divy, divz) == (1, 1, 1): return verts, faces bm = bmesh.new() [bm.verts.new(co) for co in verts] bm.verts.index_update() for face in faces: bm.faces.new(tuple(bm.verts[i] for i in face)) bm.faces.index_update() dist = 0.0001 section_dict = {0: divx, 1: divy, 2: divz} for axis in range(3): num_sections = section_dict[axis] if num_sections == 1: continue step = 1 / num_sections v1 = Vector(tuple((b if (i == axis) else 0) for i in [0, 1, 2])) v2 = Vector(tuple((-b if (i == axis) else 0) for i in [0, 1, 2])) for section in range(num_sections): mid_vec = v1.lerp(v2, section * step) plane_no = v2 - mid_vec plane_co = mid_vec visible_geom = bm.faces[:] + bm.verts[:] + bm.edges[:] bmesh.ops.bisect_plane(bm, geom=visible_geom, dist=dist, plane_co=plane_co, plane_no=plane_no, use_snap_center=False, clear_outer=False, clear_inner=False) indices = lambda i: [j.index for j in i.verts] verts = [v.co.to_tuple() for v in bm.verts] faces = [indices(face) for face in bm.faces] edges = [indices(edge) for edge in bm.edges] return verts, edges, faces
def sv_main(v=[[]], point=[], mdist=0.4): in_sockets = [ ['v', 'verts', v], ['v', 'point', point], ['s', 'mdist', mdist] ] affected_verts = {} return_verts = [] if (v and v[0]) and point: v = v[0] size = len(v) kd = kdtree.KDTree(size) for i, vtx in enumerate(v): kd.insert(Vector(vtx), i) kd.balance() # makes edges vtx = point[0][0] for (co, index, dist) in kd.find_range(vtx, mdist): affected_verts[index] = dist v1 = Vector(vtx) add_vert = return_verts.append for idx, vert in enumerate(v): rv = affected_verts.get(idx, 0) if rv > 0: amp = mdist / rv v2 = Vector(v[idx]) v3 = v1.lerp(v2, amp) # make new vector rv = v3[:] else: rv = vert add_vert(rv) # out boilerplate out_sockets = [ ['v', 'Modified', [return_verts]] ] return in_sockets, out_sockets
def do_update_heat_map(node_list, nodes): """ Create a heat map for the node tree, under development. """ global DEBUG_MODE times = [] total_test = 0 node_list = list(node_list) for name in node_list: if name in nodes: start = time.perf_counter() nodes[name].update() delta = time.perf_counter() - start total_test += delta if data_structure.DEBUG_MODE: print("Updated {0} in: {1}".format(name, round(delta, 4))) times.append(delta) if data_structure.DEBUG_MODE: print("Layout updated in: {0} seconds".format(round(total_test, 4))) if not times: return if not nodes.id_data.sv_user_colors: color_data = { node.name: (node.color[:], node.use_custom_color) for node in nodes } nodes.id_data.sv_user_colors = str(color_data) t_max = max(times) addon_name = data_structure.SVERCHOK_NAME addon = bpy.context.user_preferences.addons.get(addon_name) if addon: # to use Vector.lerp cold = Vector(addon.preferences.heat_map_cold) hot = addon.preferences.heat_map_hot else: print("Cannot find preferences") cold = Vector((1, 1, 1)) hot = (.8, 0, 0) for name, t in zip(node_list, times): nodes[name].use_custom_color = True # linear scale. nodes[name].color = cold.lerp(hot, t / t_max)
def do_update_heat_map(node_list, nodes): """ Create a heat map for the node tree, under development. """ global DEBUG_MODE times = [] total_test = 0 node_list = list(node_list) for name in node_list: if name in nodes: start = time.perf_counter() nodes[name].update() delta = time.perf_counter()-start total_test += delta if data_structure.DEBUG_MODE: print("Updated {0} in: {1}".format(name, round(delta, 4))) times.append(delta) if data_structure.DEBUG_MODE: print("Layout updated in: {0} seconds".format(round(total_test, 4))) if not times: return if not nodes.id_data.sv_user_colors: color_data = {node.name: (node.color[:], node.use_custom_color) for node in nodes} nodes.id_data.sv_user_colors = str(color_data) t_max = max(times) addon_name = data_structure.SVERCHOK_NAME addon = bpy.context.user_preferences.addons.get(addon_name) if addon: # to use Vector.lerp cold = Vector(addon.preferences.heat_map_cold) hot = addon.preferences.heat_map_hot else: print("Cannot find preferences") cold = Vector((1, 1, 1)) hot = (.8, 0, 0) for name, t in zip(node_list, times): nodes[name].use_custom_color = True # linear scale. nodes[name].color = cold.lerp(hot, t / t_max)
def newColorWith(col, vert2loopMap): oldcolor = Vector((col[0], col[1], col[2], 1)) if seltoolsOpts.bake_vccol_mask[0]: R = seltoolsOpts.bake_vccol[0] else: R = oldcolor[0] if seltoolsOpts.bake_vccol_mask[1]: G = seltoolsOpts.bake_vccol[1] else: G = oldcolor[1] if seltoolsOpts.bake_vccol_mask[2]: B = seltoolsOpts.bake_vccol[2] else: B = oldcolor[2] newcolor = Vector((R, G, B, 1)) dopinfluence = 1.0 if vert2loopMap is not None and ivdx in vert2loopMap: dopinfluence = vert2loopMap[ivdx] tltInfl = self.opt_influence * dopinfluence if self.opt_invertInfl: tltInfl = 1.0 - tltInfl lerped = oldcolor.lerp(newcolor, tltInfl) return lerped
def newColorWith(col,vert2loopMap): oldcolor = Vector((col[0],col[1],col[2],1)) if seltoolsOpts.bake_vccol_mask[0]: R = seltoolsOpts.bake_vccol[0] else: R = oldcolor[0] if seltoolsOpts.bake_vccol_mask[1]: G = seltoolsOpts.bake_vccol[1] else: G = oldcolor[1] if seltoolsOpts.bake_vccol_mask[2]: B = seltoolsOpts.bake_vccol[2] else: B = oldcolor[2] newcolor = Vector((R,G,B,1)) dopinfluence = 1.0 if vert2loopMap is not None and ivdx in vert2loopMap: dopinfluence = vert2loopMap[ivdx] tltInfl = self.opt_influence*dopinfluence if self.opt_invertInfl: tltInfl = 1.0-tltInfl lerped = oldcolor.lerp(newcolor,tltInfl) return lerped
def rotate(sce): speed = mag * vo for index in range(1, 5): name = str(nameOfTire) + str(index) obj = bpy.data.objects[str(name)] tires.insert(index, obj) rot.y += 1 vo.y = rot.y * math.pi / 180 mag.y = objTarget.location.z #print("speed : "+ str(speed)) #car = objTarget.location.length - obj.location.length print("car " + str(car.location)) #print("> " + str(car)) #print("location: "+ str(objTarget.location.z)) rotspeed = Vector.lerp(mag, vo, speed) fps = (obj.location.x - objTarget.location.x) #print("fps : "+ str(fps)) obj.rotation_euler = Euler( (rot.x * math.pi / 180, rot.y + speed * math.pi / 180, rot.z * math.pi / 180), 'XYZ')
bpy.context.object.modifiers['Bevel'].segments = 2 bpy.context.object.modifiers['Bevel'].width = 0.03 vecrotatex(theta, baseaxis, axis) currframe = bpy.context.scene.frame_start currot = startrot center = startcenter for f in range(0, fcount, 1): fprc = f * invfcount osc = abs(sin(TWOPI * fprc)) bpy.context.scene.frame_set(currframe) # Animate location. vecrotate(TWOPI * fprc, axis, pt, rotpt) center = startcenter.lerp(stopcenter, osc) rotpt = rotpt + center current.location = rotpt current.keyframe_insert(data_path='location') # Animate rotation. currot = startrot.slerp(stoprot, jprc * fprc) current.rotation_euler = currot.to_euler() current.keyframe_insert(data_path='rotation_euler') # Animate color. #mat.diffuse_color = colorsys.hsv_to_rgb(jprc, osc, 1.0) #mat.keyframe_insert(data_path='diffuse_color') convertedColor2 = colorsys.hsv_to_rgb(jprc, osc, 1.0) current.color = [convertedColor2[0], convertedColor2[1], convertedColor2[2], 1.0]
class CharacterController(bge.types.KX_PythonComponent): """ Character Controller Component: Create a capsule for your character, set the physics type to "Character" and attach this Component to them. You can configure the Walk, Run speed and the Max Jumps on the Component panel. If your character object have Collision Bounds activated, I'd recommend to enable the "Avoid Sliding" option. If you want to make your character jump in a static direction, activate "Static Jump Direction". It means that, if the player wasn't moving when he pressed Space, the character will jump up and the player will not be able to change this during the jump. The same for when he was moving when pressed Space. Same for the rotation (Static Jump Rotation).""" args = OrderedDict([ ("Activate", True), ("Walk Speed", 0.1), ("Run Speed", 0.2), ("Max Jumps", 1), ("Avoid Sliding", True), ("Static Jump Direction", False), ("Static Jump Rotation", False), ("Smooth Character Movement", 0.0), ("Make Object Invisible", False), ]) def start(self, args): """Start Function""" self.active = args["Activate"] self.walkSpeed = args["Walk Speed"] self.runSpeed = args["Run Speed"] self.avoidSliding = args["Avoid Sliding"] self.__lastPosition = self.object.worldPosition.copy() self.__lastDirection = Vector([0, 0, 0]) self.__smoothSlidingFlag = False self.__smoothMov = clamp(args["Smooth Character Movement"], 0, 0.99) self.__smoothLast = Vector([0, 0, 0]) self.staticJump = args["Static Jump Direction"] self.__jumpDirection = [0, 0, 0] self.staticJumpRot = args["Static Jump Rotation"] self.__jumpRotation = Matrix.Identity(3) self.character = bge.constraints.getCharacter(self.object) self.character.maxJumps = args["Max Jumps"] if self.active: if args["Make Object Invisible"]: self.object.visible = False def characterMovement(self): """Makes the character walk with W,A,S,D (You can run by holding Left Shift)""" keyboard = bge.logic.keyboard.inputs keyTAP = bge.logic.KX_INPUT_JUST_ACTIVATED x = 0 y = 0 speed = self.walkSpeed if keyboard[bge.events.LEFTSHIFTKEY].active: speed = self.runSpeed if keyboard[bge.events.WKEY].active: y = 1 elif keyboard[bge.events.SKEY].active: y = -1 if keyboard[bge.events.AKEY].active: x = -1 elif keyboard[bge.events.DKEY].active: x = 1 vec = Vector([x, y, 0]) self.__smoothSlidingFlag = False if vec.length != 0: self.__smoothSlidingFlag = True # Normalizing the vector. vec.normalize() # Multiply by the speed vec *= speed # This part is to make the static jump Direction works. if not self.character.onGround: if self.staticJump: vec = self.__jumpDirection if self.staticJumpRot: self.object.worldOrientation = self.__jumpRotation.copy() else: #elif self.character.onGround: self.__jumpDirection = vec self.__jumpRotation = self.object.worldOrientation.copy() smooth = 1.0 - self.__smoothMov vec = self.__smoothLast.lerp(vec, smooth) self.__smoothLast = vec test = self.object.worldPosition.copy() self.character.walkDirection = self.object.worldOrientation * vec if vec.length != 0: self.__lastDirection = self.object.worldPosition - self.__lastPosition self.__lastPosition = self.object.worldPosition.copy() def characterJump(self): """Makes the Character jump with SPACE.""" keyboard = bge.logic.keyboard.inputs keyTAP = bge.logic.KX_INPUT_JUST_ACTIVATED if keyTAP in keyboard[bge.events.SPACEKEY].queue: self.character.jump() # def avoidSlide(self): """Avoids the character to slide. This funtion is useful when you have Collision Bounds activated.""" self.object.worldPosition.xy = self.__lastPosition.xy other = self.object.worldOrientation * self.__smoothLast if self.__lastDirection.length != 0 and other.length != 0: if self.__lastDirection.angle(other) > 0.5: if not self.__smoothSlidingFlag: self.__smoothLast = Vector([0, 0, 0]) def update(self): """Update Function""" if self.active: self.characterMovement() self.characterJump() if self.avoidSliding: self.avoidSlide()
def frame_pre(scene): #if not bpy.context.screen.is_animation_playing: #bpy.app.handlers.frame_change_pre.remove(frame_pre) obj = bpy.context.object if obj and obj.type == 'ARMATURE': awc = obj.data.aut_walk_cycle try: torso_obj = obj.pose.bones[awc.torso] l_foot_ik = obj.pose.bones[awc.l_foot_ik] r_foot_ik = obj.pose.bones[awc.r_foot_ik] except Exception as e: print("ERROR", e) bpy.app.handlers.frame_change_pre.remove(frame_pre) return amp = awc.amp openness = -awc.openness anticipation = 1 - awc.anticipation fo_rot = awc.foot_rot frame = scene.frame_current up_axis = awc.up_axis.copy() up_axis.rotate(torso_obj.matrix) side_axis = awc.side_axis.copy() side_axis.rotate(torso_obj.matrix) mat_l = obj.data.bones[awc.l_foot_ik].matrix_local.copy() mat_r = obj.data.bones[awc.r_foot_ik].matrix_local.copy() if not awc.anim: front_axis = awc.front_axis.copy() front_axis.rotate(torso_obj.matrix) #print(up_axis) step = awc.step / 2 #(anticipation - .5) frequency = awc.frequency fr = 2 * pi * frame / frequency cf = cos(fr / 2) sf = sin(fr / 2) cff = cf**2 mod = (frame / frequency - .5) % 2 f = mod >= 1 up = up_axis * cff * amp front = ((sf / 2) * step) * front_axis ant = ((anticipation - .5) * step) * front_axis side = side_axis * openness fo_rot = fo_rot * side_axis foot = l_foot_ik, r_foot_ik mat = mat_l, mat_r sign = 2 * f - 1 mod -= f mloc = Matrix.Translation( ((ant + up + sign * (front + (cff - 1) * side)))) #*mat[f])) mrot = Quaternion((mod - 1 + anticipation) * fo_rot).to_matrix() foot[f].matrix = mloc * mrot.to_4x4() * mat[f] front = front_axis * (.5 - mod) * step mloc = Matrix.Translation((ant + front + sign * side)) #*mat[f-1]) if 2 * mod <= anticipation: mrot = Quaternion( (anticipation - 2 * mod) * fo_rot).to_matrix() matr = mloc * mrot.to_4x4() elif 3 * mod - 2 >= anticipation: mrot = Quaternion( (anticipation - (3 * mod - 2)) * fo_rot).to_matrix() matr = mloc * mrot.to_4x4() else: matr = mloc foot[f - 1].matrix = matr * mat[f - 1] m_cache = {} for col_bone in awc.new_bones: if col_bone.name and col_bone.show: name = col_bone.name bone = obj.pose.bones[name] bone_dat = obj.data.bones[col_bone.name] m_local = bone_dat.matrix_local #m_ch = m_cache.get(name, Matrix.Identity(4)) m_cache[name] = m_cache.get(name, m_local) if col_bone.seq_type == 'LR': fac = sf / 2 + .5 elif col_bone.seq_type == 'M': fac = cf / 2 + .5 else: # if col_bone.seq_type == 'ES' fac = cff #mloc = Matrix.Translation(col_bone.loc1.lerp(col_bone.loc2, fac)) mrot = col_bone.qua1.slerp(col_bone.qua2, fac).to_matrix() m_cache[name] *= mrot.to_4x4() loc = col_bone.loc1.lerp(col_bone.loc2, fac) if bone_dat.use_local_location: loc.rotate(m_local) m_cache[name].translation += loc parent = bone.parent.matrix * bone_dat.parent.matrix_local.inverted( ) if col_bone.add_torso: m_cache[name].translation += parent.translation bone.matrix = m_cache[name] else: bone.matrix = parent * m_cache[name] else: # awc.anim: fr_prev = frame fs = obj.data['frame_steps'].to_dict() sfs = sorted(fs, key=lambda x: int(x)) for i, frst in enumerate(sfs): fr = int(frst) if fr > frame: left = i % 2 vec2 = Vector(fs[sfs[i - 1]][0]) vec3 = Vector(fs[sfs[i]][0]) if i >= 2: vec1 = Vector(fs[sfs[i - 2]][0]) else: vec1 = vec2 sign = (2 * left - 1) rang = (frame - fr_prev) / (fr - fr_prev) # = mod%1 # | / # | / # |/___ cf = 4 * rang * (1 - rang) * sign # or sin(rang*pi) # | __ # | / \ # |/____\_ rq = Quaternion(fs[sfs[i - 1]][1]) rrot = rq.slerp(Quaternion(fs[sfs[i]][1]), rang) _mrot = rrot.to_matrix() rvec = Matrix.Translation((vec2.lerp(vec3, rang))) mat_global = rvec * _mrot.to_4x4() torso_dat = obj.data.bones[awc.torso] torso_obj.matrix = mat_global * torso_dat.matrix_local ant = rang + anticipation / 2 # antecip real vec2 = vec2.lerp(vec3, anticipation) if ant <= 1: loc = vec1.lerp(vec3, ant) else: try: vec5 = Vector(fs[sfs[i + 2]][0]) loc = vec3.lerp(vec5, ant - 1) except: loc = vec1.lerp(vec3, ant) mt_vec2 = Matrix.Translation(vec2) mat_loc = Matrix.Translation(loc) up2 = up_axis * cf * amp mrot = Matrix.Rotation( (ant - 1) * fo_rot, 3, side_axis) * _mrot mrot.resize_4x4() lat2 = side_axis * openness if left: m_vec = Matrix.Translation((1 - cf) * lat2 + up2) l_foot_ik.matrix = mat_loc * m_vec * mrot * mat_l mt_r = Matrix.Translation(-lat2) if 2 * rang <= anticipation: mr_r = Matrix.Rotation( (anticipation - 2 * rang) * fo_rot, 3, side_axis) * _mrot elif 3 * rang - 2 >= anticipation: mr_r = Matrix.Rotation( (anticipation - (3 * rang - 2)) * fo_rot, 3, side_axis) * _mrot else: mr_r = _mrot r_foot_ik.matrix = mt_vec2 * mt_r * mr_r.to_4x4( ) * mat_r else: m_vec = Matrix.Translation(-(cf + 1) * lat2 - up2) r_foot_ik.matrix = mat_loc * m_vec * mrot * mat_r mt_l = Matrix.Translation(lat2) if 2 * rang <= anticipation: mr_l = Matrix.Rotation( (anticipation - 2 * rang) * fo_rot, 3, side_axis) * _mrot elif 3 * rang - 2 >= anticipation: mr_l = Matrix.Rotation( (anticipation - (3 * rang - 2)) * fo_rot, 3, side_axis) * _mrot else: mr_l = _mrot l_foot_ik.matrix = mt_vec2 * mt_l * mr_l.to_4x4( ) * mat_l m_cache = {} for col_bone in awc.new_bones: if col_bone.name and col_bone.show: name = col_bone.name bone = obj.pose.bones[name] bone_dat = obj.data.bones[name] #m_local = m_cache.get(name, bone_dat.matrix_local) m_local = bone_dat.matrix_local m_cache[name] = m_cache.get(name, m_local) loc1 = col_bone.loc1 loc2 = col_bone.loc2 rot1 = col_bone.qua1 rot2 = col_bone.qua2 if col_bone.seq_type == 'LR': sf = cos(rang * pi) * sign # |_ _ # | \ / # |__|____|__ # | | | # | \__/ fac = sf / 2 + .5 loc = loc1.lerp(loc2, fac) rot = rot1.slerp(rot2, fac) elif col_bone.seq_type == 'M': fac = .5 - cf / 2 loc = loc1.lerp(loc2, fac) rot = rot1.slerp(rot2, fac) else: #col_bone.seq_type == 'ES': fac = cf**2 loc = loc1.lerp(loc2, fac) rot = rot1.slerp(rot2, fac) mrot = rot.to_matrix() #mloc = Matrix.Translation(vec) m_cache[name] *= mrot.to_4x4() if bone_dat.use_local_location: loc.rotate(m_local) m_cache[name].translation += loc if col_bone.add_torso: bone.matrix = mat_global * m_cache[name] else: parent = bone.parent.matrix * bone_dat.parent.matrix_local.inverted( ) bone.matrix = parent * m_cache[name] break fr_prev = fr else: bpy.app.handlers.frame_change_pre.remove(frame_pre) scene.awc_is_preview = False
class CharacterController(bge.types.KX_PythonComponent): args = OrderedDict([ ("Activate", True), ("Walk Speed", 0.1), ("Run Speed", 0.2), ("Max Jumps", 1), ("Avoid Sliding", True), ("Static Jump Direction", False), ("Static Jump Rotation", False), ("Smooth Character Movement", 0.0), ("Make Object Invisible", False), ]) # Start Function def start(self, args): self.active = args["Activate"] self.walkSpeed = args["Walk Speed"] self.runSpeed = args["Run Speed"] self.avoidSliding = args["Avoid Sliding"] self.__lastPosition = self.object.worldPosition.copy() self.__lastDirection = Vector([0, 0, 0]) self.__smoothSlidingFlag = False self.__smoothMov = clamp(args["Smooth Character Movement"], 0, 0.99) self.__smoothLast = Vector([0, 0, 0]) self.staticJump = args["Static Jump Direction"] self.__jumpDirection = [0, 0, 0] self.staticJumpRot = args["Static Jump Rotation"] self.__jumpRotation = Matrix.Identity(3) self.character = bge.constraints.getCharacter(self.object) self.character.maxJumps = args["Max Jumps"] if self.active: if args["Make Object Invisible"]: self.object.visible = False # Makes the character walk with W,A,S,D (You can run by holding Left Shift) def characterMovement(self): keyboard = bge.logic.keyboard.inputs keyTAP = bge.logic.KX_INPUT_JUST_ACTIVATED x = 0 y = 0 speed = self.walkSpeed if keyboard[bge.events.LEFTSHIFTKEY].values[-1]: speed = self.runSpeed if keyboard[bge.events.WKEY].values[-1]: y = 1 elif keyboard[bge.events.SKEY].values[-1]: y = -1 if keyboard[bge.events.AKEY].values[-1]: x = -1 elif keyboard[bge.events.DKEY].values[-1]: x = 1 vec = Vector([x, y, 0]) self.__smoothSlidingFlag = False if vec.length != 0: self.__smoothSlidingFlag = True # Normalizing the vector. For some reason, the mathutils normalize # don't work very well. vec /= vec.length # Multiply by the speed vec *= speed # This part is to make the static jump Direction works. if not self.character.onGround: if self.staticJump: vec = self.__jumpDirection if self.staticJumpRot: self.object.worldOrientation = self.__jumpRotation.copy() else: #elif self.character.onGround: self.__jumpDirection = vec self.__jumpRotation = self.object.worldOrientation.copy() smooth = 1.0 - self.__smoothMov vec = self.__smoothLast.lerp(vec, smooth) self.__smoothLast = vec test = self.object.worldPosition.copy() self.character.walkDirection = self.object.worldOrientation * vec #if self.__smoothLast.length <= 0.001 and not self.__smoothSlidingFlag: # self.__smoothLast = Vector([0,0,0]) if vec.length != 0: self.__lastDirection = self.object.worldPosition - self.__lastPosition self.__lastPosition = self.object.worldPosition.copy() # Makes the Character jump with SPACE. def characterJump(self): keyboard = bge.logic.keyboard.inputs keyTAP = bge.logic.KX_INPUT_JUST_ACTIVATED if keyTAP in keyboard[bge.events.SPACEKEY].queue: self.character.jump() # Avoids the character to slide. This funtion is useful when you have # Collision Bounds activated. def avoidSlide(self): self.object.worldPosition[0] = self.__lastPosition[0] self.object.worldPosition[1] = self.__lastPosition[1] other = self.object.worldOrientation * self.__smoothLast if self.__lastDirection.length != 0 and other.length != 0: if self.__lastDirection.angle(other) > 0.5: if not self.__smoothSlidingFlag: self.__smoothLast = Vector([0, 0, 0]) # Update Function def update(self): if self.active: self.characterMovement() self.characterJump() if self.avoidSliding: self.avoidSlide()