def generate(self): """ Generate the rig. Do NOT modify any of the original bones, except for adding constraints. The main armature should be selected and active before this is called. """ ctrl_bones = self.fk_limb.generate() thigh = ctrl_bones[0] shin = ctrl_bones[1] foot = ctrl_bones[2] foot_mch = ctrl_bones[3] # Position foot control bpy.ops.object.mode_set(mode='EDIT') eb = self.obj.data.edit_bones foot_e = eb[foot] vec = Vector(eb[self.org_bones[3]].vector) vec.normalize() foot_e.tail = foot_e.head + (vec * foot_e.length) foot_e.roll = eb[self.org_bones[3]].roll bpy.ops.object.mode_set(mode='OBJECT') # Create foot widget ob = create_widget(self.obj, foot) if ob is not None: verts = [(0.7, 1.5, 0.0), (0.7, -0.25, 0.0), (-0.7, -0.25, 0.0), (-0.7, 1.5, 0.0), (0.7, 0.723, 0.0), (-0.7, 0.723, 0.0), (0.7, 0.0, 0.0), (-0.7, 0.0, 0.0)] edges = [(1, 2), (0, 3), (0, 4), (3, 5), (4, 6), (1, 6), (5, 7), (2, 7)] mesh = ob.data mesh.from_pydata(verts, edges, []) mesh.update() mod = ob.modifiers.new("subsurf", 'SUBSURF') mod.levels = 2 return [thigh, shin, foot, foot_mch]
def write_camera(self, camera, name="Active Camera"): pos, target, up = camera.GetOrientation() bpy.ops.object.add(type='CAMERA', location=pos) ob = self.context.object ob.name = name z = (Vector(pos) - Vector(target)) x = Vector(up).cross(z) y = z.cross(x) x.normalize() y.normalize() z.normalize() ob.matrix_world.col[0] = x.resized(4) ob.matrix_world.col[1] = y.resized(4) ob.matrix_world.col[2] = z.resized(4) cam = ob.data aspect_ratio = camera.aspect_ratio fov = camera.fov if aspect_ratio == False: # we seem to be using dynamic / screen aspect ratio sketchupLog("CAMERA {} uses dynamic / screen aspect ratio ".format(name)) aspect_ratio = self.aspect_ratio if fov == False: sketchupLog("CAMERA {} is ortho ".format(name)) cam.type = 'ORTHO' else: cam.angle = (pi * fov / 180 ) * aspect_ratio cam.clip_end = self.prefs.camera_far_plane cam.name = name
def scale_bone_from_origin(bone_name, length): """ returns the bone tail Vector(x,y,z) """ direction = Vector(amt.edit_bones[bone_name].tail) - Vector(amt.edit_bones[bone_name].head) direction.normalize() direction *= length return Vector(amt.edit_bones[bone_name].head) + direction
def normalAt(self, t): tan = self.tangentAt(t) # Rotate the normal along the Z-up axis normal = Vector((tan.y, -tan.x, tan.z)) normal.normalize() return normal
def triangle_relative_to_verts(top, base_relative, base_length): v1 = Vector(top) v = Vector([-base_relative[1] / 2, base_relative[0] / 2]) v.normalize() v *= base_length / 2 vb = Vector(base_relative) v2 = v1 + vb + v v3 = v1 + vb - v return v1, v2, v3
def depth_cast(self, xy, radius=0, cached=True, coords='REGION'): xy = self.convert_ui_coord(xy, coords, 'REGION', False) radius = int(radius) search = (radius > 0) radius = max(radius, 1) sz = radius * 2 + 1 # kernel size w, h = sz, sz zbuf = self.read_zbuffer(xy, (sz, sz), centered=True, cached=cached) def get_pos(x, y): wnd_x = min(max(x+radius, 0), w-1) wnd_y = min(max(y+radius, 0), h-1) z = zbuf[wnd_x + wnd_y * w] if (z >= 1.0) or (z < 0.0): return None d = self.zbuf_to_depth(z) return self.unproject((xy[0]+x, xy[1]+y), d) cx, cy = 0, 0 center = None if search: rr = radius * radius for dxy in self.__radial_search_pattern: if dxy[2] > rr: break p = get_pos(dxy[0], dxy[1]) if p is not None: cx, cy = dxy[0], dxy[1] center = p break else: center = get_pos(0, 0) if center is None: return (False, None, Matrix(), Vector(), Vector()) normal_count = 0 normal = Vector() last_i = -10 # just some big number last_p = None neighbors = ((-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1)) for i, nbc in enumerate(neighbors): nbx, nby = nbc p = get_pos(cx + nbx, cy + nby) if p is None: continue if (i - last_i) < 4: d0 = last_p - center d1 = p - center normal += d0.cross(d1).normalized() normal_count += 1 last_p = p last_i = i if normal_count > 1: normal.normalize() return (True, None, Matrix(), center, normal)
def create_geometry(self, bm, e_loops): geom_extruded = bmesh.ops.extrude_edge_only(bm, edges=e_loops)["geom"] self.offset_verts = offset_verts = [e for e in geom_extruded if isinstance(e, bmesh.types.BMVert)] self.offset_edges = offset_edges = [e for e in geom_extruded if isinstance(e, bmesh.types.BMEdge)] self.side_faces = side_faces = [f for f in geom_extruded if isinstance(f, bmesh.types.BMFace)] bmesh.ops.recalc_face_normals(bm, faces=side_faces) self.side_edges = side_edges = [e.link_loops[0].link_loop_next.edge for e in offset_edges] for f in side_faces: f.select = True extended_verts = self.extended_verts self.v_v_pairs = v_v_pairs = dict() # keys is offset vert, # values is original vert. for e in side_edges: v1, v2 = e.verts if v1 in offset_verts: v_offset, v_orig = v1, v2 else: v_offset, v_orig = v2, v1 v_v_pairs[v_offset] = v_orig if v_orig in extended_verts: extended_verts.add(v_offset) self.faces = faces = bmesh.ops.edgeloop_fill(bm, edges=offset_edges, mat_nr=0, use_smooth=False)["faces"] self.l_fn_pairs = l_fn_pairs = dict() # loop - face normal pairs. for face in faces: face.loops.index_update() if face.normal.dot(v_v_pairs[face.verts[0]].normal) < 0.0: face.normal_flip() for fl in face.loops: edge = fl.link_loop_radial_next.link_loop_next.link_loop_next.edge co = 0 normal = Vector((0.0, 0.0, 0.0)) for f in edge.link_faces: if f not in side_faces and not f.hide and f.normal.length: normal += f.normal co += 1 if f.select: l_fn_pairs[fl] = f.normal.copy() break else: if co: normal.normalize() l_fn_pairs[fl] = normal # Be careful, if you flip face normal after # this line, l_fn_pairs won't work as you expect # because face.normal_flip() changes loop order in # the face. return faces
def polygon_normal_angle_D(verts, poly, D): ''' The angle between the polygon normal and the given direction ''' N = polygon_normal(verts, poly) v1 = Vector(N) v2 = Vector(D) v1.normalize() v2.normalize() angle = acos(v1.dot(v2)) # the angle in radians return angle
def shape_square(context, orientation): center = context.scene.cursor_location active = context.active_object zed = active.location[2] base_dir = active.location.xy - center.xy diagonal = base_dir.length if orientation == 'XY': zero_dir = get_xy_corner(base_dir).resized(3) else: zero_dir = base_dir.xy.resized(3) num_objects = len(context.selected_objects) num_side_objects = (num_objects // 4) - 1 ortho_angle = math.pi * 0.5 ortho_dir = Vector(zero_dir) ortho_dir.rotate(Euler((0, 0, ortho_angle * 0.5))) ortho_dir.normalize() # sort objects based on angle to center sorted_objects = sorted(context.selected_objects, key=lambda ob: get_angle(base_dir, ob, center)) corners = [] for i in range(0, num_objects, num_side_objects + 1): corners.append(sorted_objects[i]) assert(len(corners) == 4) sides = [ob for ob in sorted_objects if ob not in corners] side_step = math.sqrt(2 * (diagonal ** 2)) / (num_side_objects + 1) for i in range(4): # corner angle = ortho_angle * i euler = Euler((0, 0, -angle)) direction = Vector(zero_dir) direction.rotate(euler) corners[i].location = center + direction corners[i].location[2] = zed side_dir = Vector(ortho_dir) side_dir.rotate(euler) for j in range(num_side_objects): ob = sides[(i * num_side_objects) + j] step = (j + 1) * side_step ob.location = center + direction ob.location.xy -= side_dir.xy * step ob.location[2] = zed
def setCursor(self, v): if self.stepLengthEnable: c = CursorAccess.getCursor() if (Vector(c) - Vector(v)).length > 0: if self.stepLengthMode == "Absolute": v = Vector(v) - Vector(c) v.normalize() v = v * self.stepLengthValue + Vector(c) if self.stepLengthMode == "Proportional": v = (Vector(v) - Vector(c)) * self.stepLengthValue + Vector(c) CursorAccess.setCursor(Vector(v))
def polygon_normal_angle_P(verts, poly, P): ''' The angle between the polygon normal and the vector from polygon center to given point ''' N = polygon_normal(verts, poly) C = polygon_center(verts, poly) V = [P[0] - C[0], P[1] - C[1], P[2] - C[2]] v1 = Vector(N) v2 = Vector(V) v1.normalize() v2.normalize() angle = acos(v1.dot(v2)) # the angle in radians return angle
def nextpoint(poi,powers): verts_ = [poi-pow for pow in powers] vect = Vector() for i in verts_: vect+=i*(1/i.length**2) vect.normalize() # additional power: #cos(x) #sin #3*exp(-(x**2+3**2)**2) vertnext = poi + vect*(1/lent) return vertnext
def react(self, position, direction, population): res = Vector((0, 0, 0)) for individue in population: diff = individue.position - position diff = -diff if True : print(" agora ") diff.normalize() res += diff res.normalize() res = res * 5 return res
def _createBone(self, bone, armature): name = bone.name() print(" Creation of the bone '%s'..." % name) bl_bone = armature.edit_bones.new(name) bl_bone.head = bone.pivot_point.to_tuple() if bone.usedChildrenCount() == 1: bl_bone.tail = bone.children[0].pivot_point.to_tuple() elif bone.usedChildrenCount() > 1: done = False if self.smart_bone_parenting: max_depth = 0 max_depth_bones = [] for child in bone.usedChildren(): depth = child.depth(self.only_used_bones) if depth > max_depth: max_depth = depth max_depth_bones = [child] elif depth == max_depth: max_depth_bones.append(child) print("%s - %d - %d" % (bone.name(), max_depth, len(max_depth_bones))) if len(max_depth_bones) == 1: bl_bone.tail = max_depth_bones[0].pivot_point.to_tuple() done = True if not(done): v = Vector( (0, 0, 0) ) for child in bone.usedChildren(): v += child.pivot_point bl_bone.tail = (v / bone.usedChildrenCount()).to_tuple() elif bone.parent is not None: if bone.parent.bl_bone is None: self._createBone(bone.parent, armature) v = (bone.pivot_point - bone.parent.pivot_point) if v.length >= 0.001: v.normalize() bl_bone.tail = (bone.parent.bl_bone.length * v + bone.pivot_point).to_tuple() else: bl_bone.tail = (bone.parent.bl_bone.length * bone.pivot_point.normalized() + bone.pivot_point).to_tuple() else: bl_bone.tail = (bone.pivot_point * 2).to_tuple() if bone.parent is not None: bl_bone.parent = bone.parent.bl_bone bl_bone.use_connect = (bone.parent.usedChildrenCount() == 1) bone.bl_bone = bl_bone
def spherize(context): print ("in spherize") #influence influence = context.scene['unt_spherifyratio'] #gets the location of the center of the center object if context.scene.centerobject: center = bpy.data.objects[context.scene.centerobject].location else: center = bpy.context.scene.cursor_location #get world matrix for the object worldmatrix = bpy.context.object.matrix_world ob = bpy.context.object obdata = ob.data #mandatory stupid step, calculate normals split, in object mode bpy.ops.object.mode_set(mode="OBJECT") obdata.calc_normals_split() #prepare a list for all the normals. One per "loop"(vertice-per-faace) normals = [Vector()]*len(obdata.loops) #loop all the loops (subvertices) in the mesh for loop in obdata.loops: #obdata.calc_normals_split() vertexindex = loop.vertex_index normals[loop.index] = loop.normal print ("normal: %s"% normals[loop.index]) #if the vertex is selected, normalize the normal if obdata.vertices[vertexindex].select: #get local coordinate of the related vertex localco = obdata.vertices[vertexindex].co #calculate the globla coordinates of the vertex globalco = worldmatrix * obdata.vertices[vertexindex].co #delta betwen the global location of the vertex and the center of the center object v= Vector([y-x for x,y in zip(globalco,center)]) v.negate() v.normalize() #resulting vector (v*influence + normal*(1-influence)) normals[loop.index] = v * float(influence) + normals[loop.index] * (float(1)-float(influence)) #normals[loop.index].negate() normals[loop.index].normalize() print ("new normal: %s"% normals[loop.index]) obdata.normals_split_custom_set(normals) bpy.ops.object.mode_set(mode="EDIT")
def add_pole(end,ray,length,r,backup): vray = Vector(ray) vray.normalize() vend = Vector(end) center = vend - vray*(length/2+r+backup) ang = Vector((0,0,1)).rotation_difference(vray).to_euler() add_cylinder(center,ang,r,length) cyl_name = get_last_object('Cylinder') add_sphere(vend-(r+backup)*vray,r) sph_name = get_last_object('Sphere') bpy.ops.object.select_pattern(pattern=cyl_name,extend=False) bpy.ops.object.select_pattern(pattern=sph_name,extend=True) bpy.ops.object.join() return sph_name
def averageNormal(self): weight_norx = 0. weight_nory = 0. weight_norz = 0. aver_normal = None for poly in self.select_poly: weight_norx = weight_norx + (poly.normal.x * poly.area) weight_nory = weight_nory + (poly.normal.y * poly.area) weight_norz = weight_norz + (poly.normal.z * poly.area) aver_normal = Vector((weight_norx, weight_nory, weight_norz)) aver_normal.normalize() return aver_normal
def calc_average_fnorm(self): self.e_fn_pairs = e_fn_pairs = dict() # edge:average_face_normal pairs. e_lp_pairs = self.e_lp_pairs for e in self.offset_edges: loops = e_lp_pairs[e] if loops: normal = Vector() for lp in loops: normal += lp.face.normal normal.normalize() e_fn_pairs[e] = normal else: e_fn_pairs[e] = None
def adhesion(loc, bvhtree, max_l): # Compute the adhesion vector by finding the nearest point nearest_location, *_ = bvhtree.find_nearest(loc, max_l) adhesion_vector = Vector((0.0, 0.0, 0.0)) if nearest_location is not None: # Compute the distance to the nearest point adhesion_vector = nearest_location - loc distance = adhesion_vector.length # If it's less than the maximum allowed and not 0, continue if distance: # Compute the direction vector between the closest point and loc adhesion_vector.normalize() adhesion_vector *= 1.0 - distance / max_l # adhesion_vector *= getFaceWeight(ob.data, nearest_result[3]) return adhesion_vector
def execute(self, context): obj_curr = context.active_object obj_curr.update_from_editmode() mesh = obj_curr.data bm = bmesh.from_edit_mesh(mesh) vertex_normal_weight_layer = bm.verts.layers.int['vertex-normal-weight'] vertex_normal_x_layer = bm.verts.layers.float['vertex-normal-x'] vertex_normal_y_layer = bm.verts.layers.float['vertex-normal-y'] vertex_normal_z_layer = bm.verts.layers.float['vertex-normal-z'] # Determine enumerated vertex normal weight value. vertex_normal_weight = self.vertex_normal_weight_map[self.type] # Select vertices by given vertex normal weight. if self.action == 'GET': context.tool_settings.mesh_select_mode = (True, False, False) for v in bm.verts: if v[vertex_normal_weight_layer] == vertex_normal_weight: v.select = True else: v.select = False bm.select_mode = {'VERT'} bm.select_flush_mode() # Assign given vertex normal weight to selected vertices. elif self.action == 'SET': selected_verts = [v for v in bm.verts if v.select] for v in selected_verts: v[vertex_normal_weight_layer] = vertex_normal_weight # Set unweighted vertex normal component values. if self.type == 'UNWEIGHTED': mesh.calc_normals_split() for v in selected_verts: n = Vector() for loop in v.link_loops: n += mesh.loops[loop.index].normal n.normalize() v[vertex_normal_x_layer] = n.x v[vertex_normal_y_layer] = n.y v[vertex_normal_z_layer] = n.z # Update the mesh. bmesh.update_edit_mesh(mesh) if self.action == 'SET' and self.update: bpy.ops.mesh.yavne_update_vertex_normals() return {'FINISHED'}
def repeal_particles(self, iterations=20, factor=0.01): particles = list(self.particles) tree = KDTree(len(particles)) for index, particle in enumerate(particles): tree.insert(particle.co, index) tree.balance() for i in range(iterations): new_tree = KDTree(len(self.particles)) for index, particle in enumerate(particles): if particle.tag in {"SHARP", "GREASE"}: continue d = Vector() for loc, other_index, dist in tree.find_n(particle.co, 3): if dist == 0: continue other = particles[other_index] vec = particle.co - other.co d += (vec / (dist ** 3)) if not self.triangle_mode: u = particle.dir v = u.cross(particle.normal) for vec in (u + v, u - v, -u + v, -u - v): vec *= particle.radius vec += other.co vec -= particle.co dist = vec.length d -= vec * 0.3 / (dist ** 3) d.normalize() location, normal, dir, s, c = self.field.sample_point(particle.co + (d * factor * particle.radius)) if location: particle.co = location particle.normal = normal self.grid.update(particle) particle.dir = dir new_tree.insert(particle.co, index) new_tree.balance() tree = new_tree yield i
def conformHeight(tree): # retrieve float from UI threshold = bpy.data.scenes['Scene'].my_tool.conform_threshold tree_p = tree.getroot() #READ XML for venue in tree_p: for Sector in venue.findall('Sector'): for Seat in Sector: # Get Position Data posX, posY, posZ = float(Seat.get('px')), float(Seat.get('py')), float(Seat.get('pz')) rotY = radians(float(Seat.get('ry'))) vec = mathutils.Vector((-posX,-posZ,posY)) # vec.rotate(Matrix.Rotation(radians(180), 3, 'Z')) obj = bpy.context.object vecDir = mathutils.Vector((math.sin(rotY), math.cos(rotY), 0)) origin = vec + (vecDir*(threshold)) direction = Vector((0, 0, 1)) direction.normalize() def ray_cast(): sol = obj.ray_cast(origin + direction * 1000.0, -direction) location = sol[1] return location ray_cast() loc = ray_cast() new_height = (loc[2]) new_height_f = '{:.3f}'.format(new_height) Seat.set('py', new_height_f)
def calculate_normal(vertex): #vertex has link_faces <= 2 and an adjacent inner vertex if len(vertex.link_faces) <= 2: for e in vertex.link_edges: v = e.other_vert(vertex) if not is_boundary_vertex(v): return calculate_normal(v) for f in vertex.link_faces: for v in f.verts: if not is_boundary_vertex(v): return calculate_normal(v) n = Vector((0,0,0)) for f in vertex.link_faces: n += f.normal return n #vertex has link_faces <= 2 but no adjacent inner vertex if len(vertex.link_faces) == 1: return vertex.link_faces[0].normal if len(vertex.link_faces) == 2: fn1 = vertex.link_faces[0].normal fn2 = vertex.link_faces[1].normal n1 = bisector_plane(fn1, fn2) e = [] for v in get_adjacent_vertices(vertex): if is_boundary_vertex(v): e.append(vertex.co - v.co) n = intersect_planes(n1, e[0].cross(e[1])) n.normalize() return n #vertex has link_faces >= 3 normals = bisector_planes(vertex) n1 = normals[0] for n in normals: if (n-n1).length > error: n2 = n break n = intersect_planes(n1, n2) n.normalize() for face in vertex.link_faces: if face.normal.dot(n) < 0: return -n return n
def center_normal(points): center = Vector((0, 0, 0)) for i in points: center += i center /= len(points) normals = [] curr_vect = points[0] - center for point in points[1:]: new_vect = point - center normals.append(new_vect.cross(curr_vect)) curr_vect = new_vect normal = Vector((0, 0, 0)) normal = (points[0] - center).cross(points[len(points) // 4] - center) # for i in normals: # normal += i normal.normalize() return center, normal
def recalculateNormals(obj): """ Recalculates the normals of a |KX_GameObject|, |KX_MeshProxy| or |KX_PolyProxy|. It iterates through all the given vertex, it may be a slow operation, use with caution. """ if type(obj) is types.KX_GameObject: mesh = obj.meshes[0] elif type(obj) is types.KX_MeshProxy: mesh = obj elif type(obj) is types.KX_PolyProxy: mesh = obj.getMesh() else: raise ValueError("Argument must be KX_GameObject, KX_MeshPoxy or KX_PolyProxy, not " + str(type(obj))) verdict = {} #Vertex Dictionary LOL #Iterate throught Faces and make a list with all the vertex and the normals of the faces the are part of. if type(obj) is not types.KX_PolyProxy: for i in range(mesh.numPolygons): poly = mesh.getPolygon(i) normal = getPolyNormal(poly) for j in range(poly.getNumVertex()): try: verdict[poly.getVertexIndex(j)].append(normal) except KeyError: verdict[poly.getVertexIndex(j)] = [normal] else: poly = obj normal = getPolyNormal(poly) for j in range(poly.getNumVertex()): try: verdict[poly.getVertexIndex(j)].append(normal) except KeyError: verdict[poly.getVertexIndex(j)] = [normal] #Iterate throught the list recalculating the normal of each vertex. for i, normals in verdict.items(): normal = Vector([0,0,0]) for n in normals: normal += n s = len(normals) if s == 0: continue normal.x /= s normal.y /= s normal.z /= s normal.normalize() mesh.getVertex(0, i).setNormal(normals[0].to_tuple())
def color_to_normals(mesh, src_vcol): # ensure the mesh has empty split normals if not mesh.has_custom_normals: mesh.create_normals_split() mesh.use_auto_smooth = True # create a structure that matches the required input of the normals_split_custom_set function clnors = [Vector()] * len(mesh.loops) for loop_index, loop in enumerate(mesh.loops): c = src_vcol.data[loop_index].color # remap color to normal range n = Vector([remap(channel, 0.0, 1.0, -1.0, 1.0) for channel in c[0:3]]) n.normalize() clnors[loop_index] = n mesh.normals_split_custom_set(clnors) mesh.update()
def match(self): owner = self.owner p1 = Vector((owner.worldPosition.x, owner.worldPosition.y)) matching = Vector((0,0)) close = 0 for sheep in owner.flock: p2 = Vector((sheep.worldPosition.x, sheep.worldPosition.y)) dist = (p1 - p2).magnitude if dist < self.r2: sheepFace = sheep.orientation[:][1] sheepFace = Vector((sheepFace.x,sheepFace.y)) matching += sheepFace close += 1 matching /= close matching.normalize() self.direction += 4 * matching
def save(self, ctx, filename): start_time = process_time() self._file = BH3File() self._model = ctx.scene.objects.active # self._mesh = object_.data self._mesh = self._model.to_mesh(ctx.scene, True, 'PREVIEW', True) self._mesh.calc_normals_split() uv_layer = self._mesh.uv_layers.active self._uv_loops = uv_layer.data if uv_layer is not None else None for v in self._mesh.vertices: average_normal = Vector() for loop in self._mesh.loops: if loop.vertex_index == v.index: average_normal += loop.normal average_normal.normalize() self._normals.append(average_normal) skin_mod = None for modifier in self._model.modifiers: if type(modifier) is bpy.types.ArmatureModifier: skin_mod = modifier break skin = skin_mod.object ctx.scene.objects.active = skin bpy.ops.object.mode_set(mode='EDIT') armature = skin.data self._file.root_bone = self._create_bh3_bones(armature.edit_bones[0]) for face in self._mesh.polygons: self._file.faces.append( [face.vertices[0], face.vertices[1], face.vertices[2]]) bpy.ops.object.mode_set(mode='OBJECT') ctx.scene.objects.active = self._model bpy.data.meshes.remove(self._mesh) self._file.write(filename) print("BH3 export took {:f} seconds".format(process_time() - start_time)) return {'FINISHED'}
def save(self, ctx, filename): start_time = process_time() self._file = BH3File() self._model = ctx.scene.objects.active # self._mesh = object_.data self._mesh = self._model.to_mesh(ctx.scene, True, 'PREVIEW', True) self._mesh.calc_normals_split() uv_layer = self._mesh.uv_layers.active self._uv_loops = uv_layer.data if uv_layer is not None else None for v in self._mesh.vertices: average_normal = Vector() for loop in self._mesh.loops: if loop.vertex_index == v.index: average_normal += loop.normal average_normal.normalize() self._normals.append(average_normal) skin_mod = None for modifier in self._model.modifiers: if type(modifier) is bpy.types.ArmatureModifier: skin_mod = modifier break skin = skin_mod.object ctx.scene.objects.active = skin bpy.ops.object.mode_set(mode='EDIT') armature = skin.data self._file.root_bone = self._create_bh3_bones(armature.edit_bones[0]) for face in self._mesh.polygons: self._file.faces.append([face.vertices[0], face.vertices[1], face.vertices[2]]) bpy.ops.object.mode_set(mode='OBJECT') ctx.scene.objects.active = self._model bpy.data.meshes.remove(self._mesh) self._file.write(filename) print("BH3 export took {:f} seconds".format(process_time() - start_time)) return {'FINISHED'}
def _cam2world_matrix_from_cam_extrinsics(self, config): """ Determines camera extrinsics by using the given config and returns them in form of a cam to world frame transformation matrix. :param config: The configuration object. :return: The cam to world transformation matrix. """ if not config.has_param("cam2world_matrix"): position = Utility.transform_point_to_blender_coord_frame( config.get_vector3d("location", [0, 0, 0]), self.source_frame) # Rotation rotation_format = config.get_string("rotation/format", "euler") value = config.get_vector3d("rotation/value", [0, 0, 0]) if rotation_format == "euler": # Rotation, specified as euler angles rotation_euler = Utility.transform_point_to_blender_coord_frame( value, self.source_frame) elif rotation_format == "forward_vec": # Rotation, specified as forward vector forward_vec = Vector( Utility.transform_point_to_blender_coord_frame( value, self.source_frame)) # Convert forward vector to euler angle (Assume Up = Z) rotation_euler = forward_vec.to_track_quat('-Z', 'Y').to_euler() elif rotation_format == "look_at": # Compute forward vector forward_vec = value - position forward_vec.normalize() # Convert forward vector to euler angle (Assume Up = Z) rotation_euler = forward_vec.to_track_quat('-Z', 'Y').to_euler() else: raise Exception("No such rotation format:" + str(rotation_format)) cam2world_matrix = Matrix.Translation(Vector(position)) @ Euler( rotation_euler, 'XYZ').to_matrix().to_4x4() else: cam2world_matrix = Matrix( np.array(config.get_list("cam2world_matrix")).reshape( 4, 4).astype(np.float32)) return cam2world_matrix
def adhesion(loc, ob, max_l): # Get transfor vector and transformed loc tran_mat = ob.matrix_world.inverted() tran_loc = tran_mat * loc # Compute the adhesion vector by finding the nearest point nearest_result = ob.closest_point_on_mesh(tran_loc, max_l) adhesion_vector = Vector((0.0, 0.0, 0.0)) if nearest_result[2] != -1: # Compute the distance to the nearest point adhesion_vector = ob.matrix_world * nearest_result[0] - loc distance = adhesion_vector.length # If it's less than the maximum allowed and not 0, continue if distance: # Compute the direction vector between the closest point and loc adhesion_vector.normalize() adhesion_vector *= 1.0 - distance / max_l #adhesion_vector *= getFaceWeight(ob.data, nearest_result[2]) return adhesion_vector
def align_along(): act_name = utils.get_active_bone().name selected = [ x.name for x in utils.get_selected_bones() if x.name != act_name ] amt = bpy.context.object utils.mode_e() act = amt.data.edit_bones[act_name] p = Vector(act.head) vec_act = Vector(act.tail) - p vec_act.normalize() for b in selected: bone = amt.data.edit_bones[b] a = Vector(bone.head) tail = Vector(bone.tail - bone.head) bone.head = p + vec_act * (a - p).dot(vec_act) bone.tail = bone.head + tail
def update_auto_bone_roll(cls, edit_bone): # make a triangle face (p1,p2,p3) p1 = edit_bone.head.copy() p2 = edit_bone.tail.copy() p3 = p2.copy() # translate p3 in xz plane # the normal vector of the face tracks -Y direction xz = Vector((p2.x - p1.x, p2.z - p1.z)) xz.normalize() theta = math.atan2(xz.y, xz.x) norm = edit_bone.vector.length p3.z += norm * math.cos(theta) p3.x -= norm * math.sin(theta) # calculate the normal vector of the face y = (p2 - p1).normalized() z_tmp = (p3 - p1).normalized() x = y.cross(z_tmp) # normal vector # z = x.cross(y) cls.update_bone_roll(edit_bone, y.xzy, x.xzy)
def AdjustRoll_axisplane(bone, nor): props = bpy.context.scene.cyarigtools_props mat = bone.matrix z = Vector((mat[0][2], mat[1][2], mat[2][2])) z.normalize() #Xvectorを回転の正負判定に使う #X軸と法線の内積が正なら+、負ならー x = Vector((mat[0][0], mat[1][0], mat[2][0])) sign = x.dot(nor) / math.fabs(x.dot(nor)) cos_sita = z.dot(nor) sita = math.acos(cos_sita) if props.axis_plane == 'Z': bone.roll = sita * sign elif props.axis_plane == 'X': bone.roll = sita * sign + math.pi / 2
def getLabelPoint(self, edge_index, label_indent): edge = self.getEdgeByIndex(edge_index) start = Vector(edge[0]) end = Vector(edge[1]) center = Vector(((start.x + end.x) / 2, (start.y + end.y) / 2)) v = start - center v90 = Vector((-v.y, v.x)) v90.normalize() labelPoint0 = center + v90 * label_indent labelPoint1 = center - v90 * label_indent if self.isPointInside(labelPoint0): return Vector((labelPoint0[0], labelPoint0[1], 0)) elif self.isPointInside(labelPoint1): return Vector((labelPoint1[0], labelPoint1[1], 0)) else: raise Exception("Can't find label point!")
def _cam2world_matrix_from_cam_extrinsics_look_at(self, location, look_at): """ Determines camera extrinsics by using the location and the look_at vector. :param look_at: The look_at vector. :return: The cam to world transformation matrix. """ position = Vector( Utility.transform_point_to_blender_coord_frame( location, self.source_frame)) forward_vec = Vector(look_at) - position forward_vec.normalize() # Convert forward vector to euler angle (Assume Up = Z) rotation_euler = forward_vec.to_track_quat('-Z', 'Y').to_euler() cam2world_matrix = Matrix.Translation(position) @ Euler( rotation_euler, 'XYZ').to_matrix().to_4x4() return cam2world_matrix
def avoid(self): owner = self.owner avoidance = Vector((0,0)) for sheep in owner.flock: p1 = Vector((owner.worldPosition.x,owner.worldPosition.y)) p2 = Vector((sheep.worldPosition.x,sheep.worldPosition.y)) dist = (p1 - p2).magnitude theta = atan2(p1.y - p2.y,p1.x - p2.x) if .001 < dist < self.r1: size = 1/dist**2 avoidance.x += size*cos(theta) avoidance.y += size*sin(theta) env = Environment.getInstance() avoidance += env.staticAvoidanceVector(owner.worldPosition) try: ramAvoidance = owner.avoidanceVector('ram') ramDist = owner.distance('ram') if 0 < ramDist < 1.5*self.r1: ramAvoidance *= 1.5/ramDist**2 avoidance += ramAvoidance except: pass tractorDist = owner.distance('tractor') if 0 < tractorDist < 3*self.r1: avoidance += owner.avoidanceVector('tractor')*(5/tractorDist**2) if avoidance.magnitude > 0.05: owner.run() self.direction += avoidance*10 return if avoidance.magnitude > 0.04: owner.flounder() else: owner.walk() avoidance.normalize() self.direction += avoidance*10
def align_direction(): selected = [x.name for x in utils.get_selected_bones()] act_name = utils.get_active_bone().name amt = bpy.context.object utils.mode_e() act = amt.data.edit_bones[act_name] matrix = Matrix(act.matrix) if len(selected) > 0: for bonename in selected: tgt = amt.data.edit_bones[bonename] head = Vector(tgt.head) tgt.matrix = matrix l = tgt.length vec = Vector(act.tail) - Vector(act.head) vec.normalize() tgt.head = head tgt.tail = Vector(tgt.head) + vec * l
def averageNormal(self, obj, is_global): weight_norx = 0. weight_nory = 0. weight_norz = 0. aver_normal = None bm = self.getBMesh(obj.data) select_face = self.getSelectedFaces(bm) for face in select_face: weight_norx += face.normal.x * face.calc_area() weight_nory += face.normal.y * face.calc_area() weight_norz += face.normal.z * face.calc_area() aver_normal = Vector((weight_norx, weight_nory, weight_norz)) aver_normal.normalize() if is_global == True: eul_obj_rot = obj.rotation_euler aver_normal.rotate(eul_obj_rot) return aver_normal
def parse_spotfx(fw, obj, EXPORT_GLOBAL_MATRIX): from mathutils import Vector rotation = obj.rotation_euler.to_matrix() direction = Vector(EXPORT_GLOBAL_MATRIX * Vector(rotation * Vector( (0.0, 1.0, 0.0)))) direction.normalize() upVector = Vector(EXPORT_GLOBAL_MATRIX * Vector(rotation * Vector( (0.0, 0.0, 1.0)))) upVector.normalize() fw('spotFx\n') fw('{\n') fw(' name \"%s\"\n' % obj.name) fw(' group \"%s\"\n' % obj.levelGroup) fw(' origin %f %f %f\n' % Vector(EXPORT_GLOBAL_MATRIX * Vector(obj.location))[:]) fw(' direction %f %f %f\n' % direction[:]) fw(' upVector %f %f %f\n' % upVector[:]) fw(' genType %i\n' % get_enum_type( bpy.types.GeneratePropertyGroup.genType, obj.fxGen.genType)) fw(' genDelay %f\n' % obj.fxGen.genDelay) fw(' red %f\n' % obj.fxColor[0]) fw(' green %f\n' % obj.fxColor[1]) fw(' blue %f\n' % obj.fxColor[2]) fw(' activeDelay %f\n' % obj.fxActiveDelay) fw(' inactiveDelay %f\n' % obj.fxInactiveDelay) fw(' primaryID %i\n' % get_enum_type(bpy.types.Object.fxPrimaryID, obj.fxPrimaryID)) fw(' secondaryID %i\n' % get_enum_type(bpy.types.Object.fxSecondaryID, obj.fxSecondaryID)) fw(' SFX \"%s\"\n' % obj.fxSFX) fw(' volume %f\n' % obj.fxVolume) fw(' speed %f\n' % obj.fxSpeed) fw(' type %i\n' % get_enum_type(bpy.types.Object.fxType, obj.fxType)) fw(' sfxType %i\n' % get_enum_type(bpy.types.Object.sfxType, obj.sfxType)) fw('}\n\n')
def visualizeCovariance(kf_x, P): # Visualize CoVariance Matrix P: # Source: https://geus.wordpress.com/2011/09/15/how-to-represent-a-3d-normal-function-with-ros-rviz/ # get Eigenvalues and Eigenvectors of P: (eigValues, eigVectors) = np.linalg.eig( P) # Possible Bug: Required to reduce to 3x3 Matrix eigx = Vector([eigVectors[0, 0], eigVectors[0, 2], eigVectors[0, 4]]) eigy = Vector([eigVectors[2, 0], eigVectors[2, 2], eigVectors[2, 4]]) eigz = Vector([eigVectors[4, 0], eigVectors[4, 2], eigVectors[4, 4]]) eigx.normalize() eigy.normalize() eigz.normalize() # build rotation matrix: rot = Matrix([eigx, eigy, eigz]) rot.transpose() # retrieve Quaternion quat = rot.to_quaternion() # update sphere object: covObject.location.x = kf_x[0] covObject.location.y = kf_x[2] covObject.location.z = kf_x[4] covObject.rotation_quaternion = quat covObject.scale.x = eigValues[0] * 100 covObject.scale.y = eigValues[2] * 100 covObject.scale.z = eigValues[4] * 100 covObject.keyframe_insert(data_path="location") covObject.keyframe_insert(data_path="rotation_quaternion") covObject.keyframe_insert(data_path="scale")
def compact_vertices(self, unique_indices, split_normals): for new_idx, old_idx in enumerate(unique_indices): normal = Vector() for n in split_normals[new_idx]: for i in range(3): normal[i] += n[i] normal.normalize() self.verts[new_idx] = self.verts[old_idx] self.normals[new_idx] = tuple(normal[:3]) if self.uv1: self.uv1[new_idx] = self.uv1[old_idx] if self.uv2: self.uv2[new_idx] = self.uv2[old_idx] num_unique = len(unique_indices) self.verts = self.verts[:num_unique] self.normals = self.normals[:num_unique] if self.uv1: self.uv1 = self.uv1[:num_unique] if self.uv2: self.uv2 = self.uv2[:num_unique]
def get_current_grid_vectors(scene, with_rotation=True): """Returns the current grid X/Y/Z vectors from scene data :param scene: scene data :param with_rotation: bool, rotate the grid vectors by sprytile_data :return: up_vector, right_vector, normal_vector """ data_normal = scene.sprytile_data.paint_normal_vector data_up_vector = scene.sprytile_data.paint_up_vector normal_vector = Vector((data_normal[0], data_normal[1], data_normal[2])) up_vector = Vector((data_up_vector[0], data_up_vector[1], data_up_vector[2])) normal_vector.normalize() up_vector.normalize() right_vector = up_vector.cross(normal_vector) if with_rotation: rotation = Quaternion(-normal_vector, scene.sprytile_data.mesh_rotate) up_vector = rotation * up_vector right_vector = rotation * right_vector return up_vector, right_vector, normal_vector
def parse_camera(fw, obj, EXPORT_GLOBAL_MATRIX): from mathutils import Vector rotation = obj.rotation_euler.to_matrix() direction = Vector(EXPORT_GLOBAL_MATRIX * Vector(rotation * Vector( (0.0, 1.0, 0.0)))) direction.normalize() upVector = Vector(EXPORT_GLOBAL_MATRIX * Vector(rotation * Vector( (0.0, 0.0, 1.0)))) upVector.normalize() fw('camera\n') fw('{\n') fw(' name \"%s\"\n' % obj.name) fw(' group \"%s\"\n' % obj.levelGroup) fw(' origin %f %f %f\n' % Vector(EXPORT_GLOBAL_MATRIX * Vector(obj.location))[:]) fw(' direction %f %f %f\n' % direction[:]) fw(' upVector %f %f %f\n' % upVector[:]) fw('}\n\n')
def rotation_to(a, b): """Calculates shortest Quaternion from Vector a to Vector b""" # a - up vector # b - direction to point to # http://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another # https://github.com/toji/gl-matrix/blob/f0583ef53e94bc7e78b78c8a24f09ed5e2f7a20c/src/gl-matrix/quat.js#L54 a = a.normalized() b = b.normalized() q = Quaternion() tmpvec3 = Vector() xUnitVec3 = Vector((1, 0, 0)) yUnitVec3 = Vector((0, 1, 0)) dot = a.dot(b) if (dot < -0.999999): # tmpvec3 = cross(xUnitVec3, a) tmpvec3 = xUnitVec3.cross(a) if (tmpvec3.length < 0.000001): tmpvec3 = yUnitVec3.cross(a) tmpvec3.normalize() # q = Quaternion(tmpvec3, Math.PI) q = Quaternion(tmpvec3, math.pi) elif (dot > 0.999999): q.x = 0 q.y = 0 q.z = 0 q.w = 1 else: tmpvec3 = a.cross(b) q.x = tmpvec3[0] q.y = tmpvec3[1] q.z = tmpvec3[2] q.w = 1 + dot q.normalize() return q
def pipe_geometry(A, B, n, r0, r1, closed=False, phi=0): points, faces = [], [] A, B = Vector(A), Vector(B) # Setup of vectors N = B - A N.normalize() F = N.cross((0, 0, 1)) if (F.length == 0): F, E = Vector((1, 0, 0)), Vector((0, 1, 0)) else: F.normalize() E = N.cross(F) E.normalize() if (closed): points.append(A) points.append(B) for i in range(n): t = float(i) / float(n) p0 = A + r0 * (F * cos(TAU * t + phi) + E * sin(TAU * t + phi)) p1 = B + r1 * (F * cos(TAU * t + phi) + E * sin(TAU * t + phi)) points.append(p0) points.append(p1) if (closed): idx0, idx1 = 2 * i + 2, 2 * i + 3 iNext0, iNext1 = (idx0 % (2 * n)) + 2, (idx1 % (2 * n)) + 2 faces.append((idx0, 0, iNext0)) faces.append((1, idx1, iNext1)) faces.append((idx1, idx0, iNext0, iNext1)) else: idx0, idx1 = 2 * i, 2 * i + 1 iNext0, iNext1 = (idx0 + 2) % (2 * n), (idx1 + 2) % (2 * n) faces.append((idx1, idx0, iNext0, iNext1)) return points, faces
def write_camera(self, camera, name="Active Camera"): pos, target, up = camera.GetOrientation() bpy.ops.object.add(type='CAMERA', location=pos) ob = self.context.object ob.name = name z = (Vector(pos) - Vector(target)) x = Vector(up).cross(z) y = z.cross(x) x.normalize() y.normalize() z.normalize() ob.matrix_world.col[0] = x.resized(4) ob.matrix_world.col[1] = y.resized(4) ob.matrix_world.col[2] = z.resized(4) cam = ob.data aspect_ratio = camera.aspect_ratio if camera.aspect_ratio else self.aspect_ratio cam.angle = (pi * camera.fov / 180) * aspect_ratio cam.clip_end = self.prefs.camera_far_plane cam.name = name
def create_controllers(self, amt, main_bone, txt_a, txt_b, size_a, size_b, bx, bz, roll): main_name = main_bone.name tail = main_bone.tail head = main_bone.head v1 = Vector((head[0] - tail[0], head[1] - tail[1], head[2] - tail[2],)) v1.normalize() # create controller A bone_a = amt.edit_bones.new(main_name + txt_a) bone_a.tail = head bone_a.head = (head[0] + (v1[0] * size_a), head[1] + (v1[1] * size_a), head[2] + (v1[2] * size_a)) bone_a.bbone_x = bx * 1.15 bone_a.bbone_z = bz * 1.15 bone_a.roll = roll # create controller B bone_b = amt.edit_bones.new(main_name + txt_b) bone_b.head = tail bone_b.tail = (tail[0] + (v1[0] * -size_b), tail[1] + (v1[1] * -size_b), tail[2] + (v1[2] * -size_b)) bone_b.bbone_x = bx * 1.20 bone_b.bbone_z = bz * 1.20 bone_b.roll = roll
def align_at_flontview(): #props = bpy.context.scene.cyarigtools_props #selected = [x.name for x in props.allbones ] amt = bpy.context.object utils.mode_e() selected = utils.bone.sort() bone1 = amt.data.edit_bones[selected[0]] bone2 = amt.data.edit_bones[selected[-1]] #法線を割り出す normal.y = 0 #vecのx、zを入れ替えればよい(どちらかにー符号をつける) vec0 = Vector(bone1.head) - Vector(bone2.tail) nor = Vector((vec0.z, 0, -vec0.x)) nor.normalize() p = Vector(bone1.head) for b in selected[1:]: bone = amt.data.edit_bones[b] a = Vector(bone.head) pos = a + nor * (p - a).dot(nor) bone.head = pos
def write_camera(self, camera, name="Active Camera"): pos, target, up = camera.GetOrientation() bpy.ops.object.add(type='CAMERA', location=pos) ob = self.context.object ob.name = name z = (Vector(pos) - Vector(target)) x = Vector(up).cross(z) y = z.cross(x) x.normalize() y.normalize() z.normalize() ob.matrix_world.col[0] = x.resized(4) ob.matrix_world.col[1] = y.resized(4) ob.matrix_world.col[2] = z.resized(4) cam = ob.data aspect_ratio = camera.aspect_ratio if camera.aspect_ratio else self.aspect_ratio cam.angle = (pi * camera.fov / 180 ) * aspect_ratio cam.clip_end = self.prefs.camera_far_plane cam.name = name
def add_sun(shader, function, sun_parms, i): color = [0.0, 0.0, 0.0] intensity = 1.0 parms = sun_parms.split() rotation = [0.0, 0.0] name = shader + "_" + function + "." + str(i) if function == "sun": if len(parms) < 6: print("not enogh sun parameters") elif function == "q3map_sun": if len(parms) < 6: print("not enogh q3map_sun parameters") elif function == "q3map_sunext": if len(parms) < 8: print("not enogh q3map_sunext parameters") elif function == "q3gl2_sun": if len(parms) < 9: print("not enogh q3gl2_sun parameters") color = Vector((float(parms[0]), float(parms[1]), float(parms[2]))) color.normalize() intensity = float(parms[3]) rotation = [float(parms[4]), float(parms[5])] light_vec = [0.0, 0.0, 0.0] rotation[0] = rotation[0] / 180.0 * math.pi rotation[1] = rotation[1] / 180.0 * math.pi light_vec[0] = math.cos(rotation[0]) * math.cos(rotation[1]) light_vec[1] = math.sin(rotation[0]) * math.cos(rotation[1]) light_vec[2] = math.sin(rotation[1]) angle = math.radians(1.5) QuakeLight.add_light(name, "SUN", intensity, color, light_vec, angle) return True
def execute(self, context): obj = context.active_object mesh = obj.data mesh.calc_normals_split() if '__NORMALS__' not in mesh.vertex_colors: mesh.vertex_colors.new(name="__NORMALS__") color_map = mesh.vertex_colors['__NORMALS__'] for loop in mesh.loops: i = loop.index # Convert Loop normal to a valid colour. normal = Vector(loop.normal) normal.normalize() rgb = (normal + Vector((1.0, 1.0, 1.0))) * 0.5 rgba = rgb.to_4d() # Set Vertex color to new color color_map.data[loop.index].color = rgba return {'FINISHED'}
def __init__(self, obj1, obj2, dir_vec, mode='ANGLE', Kp=0, Ki=0, Kd=0, max_torque=None, angle0=0): self.obj1 = obj1 self.obj2 = obj2 world_dir_vec = Vector(dir_vec).normalized() self.local_dir_vec1 = obj1.worldOrientation.inverted() * world_dir_vec self.local_dir_vec2 = obj2.worldOrientation.inverted() * world_dir_vec world_ang_vec = world_dir_vec.cross((0, 0, 1)) if world_ang_vec.dot(world_ang_vec) == 0: world_ang_vec = Vector((1, 0, 0)) else: world_ang_vec.normalize() self.local_ang_vec1 = obj1.worldOrientation.inverted() * world_ang_vec self.local_ang_vec2 = obj2.worldOrientation.inverted() * world_ang_vec self.mode = mode self.Kp = Kp self.Ki = Ki self.Kd = Kd self.max_torque = max_torque self.angle0 = angle0 self.value = 0 self.int_err = 0 self.prev_err = 0 self.prev_time = blenderapi.persistantstorage().time.time
def flatten(self, context, object): mesh = object.data bm = bmesh.from_edit_mesh(mesh) if bpy.context.scene.tool_settings.mesh_select_mode[0]: bpy.ops.mesh.select_mode(type="FACE") if bpy.context.scene.tool_settings.mesh_select_mode[1]: bpy.ops.mesh.select_mode(type="FACE") if bpy.context.scene.tool_settings.mesh_select_mode[2]: selected = [] # Get selected faces for f in bm.faces: if f.select: selected.append(f) # sum all selected normals sum = Vector((1, 1, 1)) for f in selected: sum = sum + f.normal length = len(selected) sum = (sum.x / length, sum.y / length, sum.z / length) sum = Vector(sum) sum.normalize() print(sum) for f in selected: for v in f.verts: v.normal = sum # f.normal_update() # bm.select_flush(True) bmesh.update_edit_mesh(mesh) mesh.update()
def matchIkLeg(legIk, toeFk, mBall, mToe, mHeel): rmat = toeFk.matrix.to_3x3() tHead = Vector(toeFk.matrix.col[3][:3]) ty = rmat.col[1] tail = tHead + ty * toeFk.bone.length zBall = mBall.matrix.col[3][2] zToe = mToe.matrix.col[3][2] zHeel = mHeel.matrix.col[3][2] x = Vector(rmat.col[0]) y = Vector(rmat.col[1]) z = Vector(rmat.col[2]) if zHeel > zBall and zHeel > zToe: # 1. foot.ik is flat if abs(y[2]) > abs(z[2]): y = -z y[2] = 0 else: # 2. foot.ik starts at heel hHead = Vector(mHeel.matrix.col[3][:3]) y = tail - hHead y.normalize() x -= x.dot(y)*y x.normalize() if abs(x[2]) < 0.7: x[2] = 0 x.normalize() z = x.cross(y) head = tail - y * legIk.bone.length # Create matrix gmat = Matrix() gmat.col[0][:3] = x gmat.col[1][:3] = y gmat.col[2][:3] = z gmat.col[3][:3] = head pmat = getPoseMatrix(gmat, legIk) insertLocation(legIk, pmat) insertRotation(legIk, pmat)
def grow(self): from numpy import sum, all, ones self.itt += 1 stp = self.stp killzone = self.killzone noise = self.noise v_xyz,s_xyz = self.get_positions() dvv,dvs = self.get_distances(v_xyz,s_xyz) vs_map,sv_map = self.make_maps(dvv,dvs,killzone) nv,ns = dvs.shape self.select_seed() bm = self.get_bmesh() nodes = [v for v in bm.verts] for i,jj in vs_map.items(): v = Vector(sum(s_xyz[jj,:]-v_xyz[i,:],axis=0)) v.normalize() # this is flawed. particularly for "flat" geometries p,pn = self.closest_point_on_geom(nodes[i].co) projected = pn.cross(v.cross(pn)) projected += random_unit_vector()*noise projected.normalize() new = nodes[i].co + projected*stp verts = [nodes[i]] new_vert = bmesh.ops.extrude_vert_indiv( bm, verts=verts)['verts'].pop() new_vert.co = new ## mask out dead sources mask = ones(ns,'bool') for j,ii in sv_map.items(): if all(dvs[ii,j]<=killzone): mask[j] = False self.num_sources -= 1 print('merging:',len(ii),'deleted source:',j) new_verts = [] for i in ii: new = bmesh.ops.extrude_vert_indiv( bm, verts=[nodes[i]])['verts'].pop() new.co = self.sources[j] new_verts.append(new) bmesh.ops.remove_doubles(bm,verts=new_verts,dist=0.01) self.dead_sources.append(self.sources[j]) self.to_mesh() self.sources = self.sources[mask,:] return
def scan_advanced(scanner_object, max_distance = 10.0, evd_file=None, add_blender_mesh = False, add_noisy_blender_mesh = False, tof_res_x = 176, tof_res_y = 144, lens_angle_w=43.6, lens_angle_h=34.6, flength = 10.0, evd_last_scan=True, noise_mu=0.0, noise_sigma=0.004, timestamp = 0.0, backfolding=False, world_transformation=Matrix()): inv_scan_x = scanner_object.inv_scan_x inv_scan_y = scanner_object.inv_scan_y inv_scan_z = scanner_object.inv_scan_z start_time = time.time() #10.0mm is currently the distance between the focal point and the sensor sensor_width = 2 * math.tan(deg2rad(lens_angle_w/2.0)) * 10.0 sensor_height = 2 * math.tan(deg2rad(lens_angle_h/2.0)) * 10.0 if tof_res_x == 0 or tof_res_y == 0: raise ValueError("Resolution must be > 0") pixel_width = sensor_width / float(tof_res_x) pixel_height = sensor_height / float(tof_res_y) bpy.context.scene.render.resolution_percentage width = bpy.context.scene.render.resolution_x height = bpy.context.scene.render.resolution_y cx = float(tof_res_x) /2.0 cy = float(tof_res_y) /2.0 evd_buffer = [] rays = [] ray_info = [] ray = Vector([0.0,0.0,0.0]) for x in range(tof_res_x): for y in range(tof_res_y): """Calculate a vector that originates at the principal point and points to the pixel in the sensor. This vector is then scaled to the maximum scanning distance """ physical_x = float(x-cx) * pixel_width physical_y = float(y-cy) * pixel_height physical_z = -float(flength) ray.xyz = [physical_x, physical_y, physical_z] ray.normalize() final_ray = max_distance*ray rays.extend([final_ray[0],final_ray[1],final_ray[2]]) """ pitch and yaw are added for completeness, normally they are not provided by a ToF Camera but can be derived from the pixel position and the camera parameters. """ yaw = math.atan(physical_x/flength) pitch = math.atan(physical_y/flength) ray_info.append([yaw, pitch, timestamp]) returns = blensor.scan_interface.scan_rays(rays, max_distance, inv_scan_x = inv_scan_x, inv_scan_y = inv_scan_y, inv_scan_z = inv_scan_z) verts = [] verts_noise = [] evd_storage = evd.evd_file(evd_file, tof_res_x, tof_res_y, max_distance) reusable_vector = Vector([0.0,0.0,0.0,0.0]) for i in range(len(returns)): idx = returns[i][-1] distance_noise = random.gauss(noise_mu, noise_sigma) #If everything works substitute the previous line with this #distance_noise = pixel_noise[returns[idx][-1]] + random.gauss(noise_mu, noise_sigma) reusable_vector.xyzw = [returns[i][1],returns[i][2],returns[i][3],1.0] vt = (world_transformation * reusable_vector).xyz v = [returns[i][1],returns[i][2],returns[i][3]] verts.append ( vt ) vector_length = math.sqrt(v[0]**2+v[1]**2+v[2]**2) norm_vector = [v[0]/vector_length, v[1]/vector_length, v[2]/vector_length] vector_length_noise = vector_length+distance_noise if backfolding: #Distances > max_distance/2..max_distance are mapped to 0..max_distance/2 if vector_length_noise >= max_distance/2.0: vector_length_noise = vector_length_noise - max_distance/2.0 reusable_vector.xyzw = [norm_vector[0]*vector_length_noise, norm_vector[1]*vector_length_noise, norm_vector[2]*vector_length_noise,1.0] v_noise = (world_transformation * reusable_vector).xyz verts_noise.append( v_noise ) evd_storage.addEntry(timestamp = ray_info[idx][2], yaw =(ray_info[idx][0]+math.pi)%(2*math.pi), pitch=ray_info[idx][1], distance=vector_length, distance_noise=vector_length_noise, x=vt[0], y=vt[1], z=vt[2], x_noise=v_noise[0], y_noise=v_noise[1], z_noise=v_noise[2], object_id=returns[i][4], color=returns[i][5], idx=returns[i][-1]) if evd_file: evd_storage.appendEvdFile() if add_blender_mesh: mesh_utils.add_mesh_from_points_tf(verts, "Scan", world_transformation) if add_noisy_blender_mesh: mesh_utils.add_mesh_from_points_tf(verts_noise, "NoisyScan", world_transformation) bpy.context.scene.update() end_time = time.time() scan_time = end_time-start_time print ("Elapsed time: %.3f"%(scan_time)) return True, 0.0, scan_time