def getMultiObjectSelectionBBox(all_ob_bounds): multibbox = {} boundsMin = Vector((99999999.0, 99999999.0)) boundsMax = Vector((-99999999.0, -99999999.0)) boundsCenter = Vector((0.0, 0.0)) for ob_bounds in all_ob_bounds: if len(ob_bounds) > 1: boundsMin.x = min(boundsMin.x, ob_bounds['min'].x) boundsMin.y = min(boundsMin.y, ob_bounds['min'].y) boundsMax.x = max(boundsMax.x, ob_bounds['max'].x) boundsMax.y = max(boundsMax.y, ob_bounds['max'].y) multibbox['min'] = boundsMin multibbox['max'] = boundsMax multibbox['width'] = (boundsMax - boundsMin).x multibbox['height'] = (boundsMax - boundsMin).y boundsCenter.x = (boundsMax.x + boundsMin.x) / 2 boundsCenter.y = (boundsMax.y + boundsMin.y) / 2 multibbox['center'] = boundsCenter multibbox['area'] = multibbox['width'] * multibbox['height'] multibbox['minLength'] = min(multibbox['width'], multibbox['height']) return multibbox
def get_island_BBOX(island): bbox = {} bm = bmesh.from_edit_mesh(bpy.context.active_object.data) uv_layers = bm.loops.layers.uv.verify() boundsMin = Vector((99999999.0, 99999999.0)) boundsMax = Vector((-99999999.0, -99999999.0)) boundsCenter = Vector((0.0, 0.0)) for face in island: for loop in face.loops: uv = loop[uv_layers].uv boundsMin.x = min(boundsMin.x, uv.x) boundsMin.y = min(boundsMin.y, uv.y) boundsMax.x = max(boundsMax.x, uv.x) boundsMax.y = max(boundsMax.y, uv.y) bbox['min'] = Vector((boundsMin)) bbox['max'] = Vector((boundsMax)) boundsCenter.x = (boundsMax.x + boundsMin.x) / 2 boundsCenter.y = (boundsMax.y + boundsMin.y) / 2 bbox['center'] = boundsCenter return bbox
def plank(face_vs, thickness, offset=Vector((0, 0, 0))): verts = [] faces = [] if len(face_vs) == 4: for j in range(0, 2): for v in face_vs: vv = Vector(v) if j == 0: vv.x = vv.x - thickness * 0.5 else: vv.x = vv.x + thickness * 0.5 vv += offset verts.append((vv.x, vv.y, vv.z)) faces = [(0, 1, 2, 3), (7, 6, 5, 4), (0, 3, 7, 4), (0, 1, 5, 4), (1, 2, 6, 5), (2, 3, 7, 6)] elif len(face_vs) == 7: for j in range(0, 2): for i in range(0, 6): vv = Vector(face_vs[i]) if j == 0: vv.x = vv.x - thickness * 0.5 else: vv.x = vv.x + thickness * 0.5 vv += offset verts.append((vv.x, vv.y, vv.z)) faces = [(0, 1, 2, 3), (3, 4, 5, 0), (9, 8, 7, 6), (6, 11, 10, 9), (0, 1, 7, 6), (1, 2, 8, 7), (2, 3, 9, 8), (3, 4, 10, 9), (4, 5, 11, 10), (5, 0, 6, 11)] return verts, faces
def correct_bone_positions(bones): for dest_name, end, root_name, root_end, axis in bones_to_correct_spine_position: root_bone = bones.get(root_name) root = Vector(getattr(root_bone, root_end)) dest = bones.get(dest_name) dest_head = Vector(dest.head) dest_tail = Vector(dest.tail) if end == "head": setattr(dest_head, axis, getattr(root, axis)) dest.head = dest_head elif end == "tail": print("set tail") setattr(dest_tail, axis, getattr(root, axis)) dest.tail = dest_tail # now do toes leftToe = bones.get("LeftToeBase") leftToeHead = Vector(leftToe.head) leftToeTail = Vector(leftToe.tail) leftToeTail.x = leftToeHead.x leftToeTail.z = leftToeHead.z leftToe.tail = leftToeTail rightToe = bones.get("RightToeBase") rightToeHead = Vector(rightToe.head) rightToeTail = Vector(rightToe.tail) rightToeTail.x = rightToeHead.x rightToeTail.z = rightToeHead.z rightToe.tail = rightToeTail
def readPackedVector(f, format): packed = f output = Vector() if format == 'XZY': output.x = packed output.y = packed / 65536.0 output.z = packed / 256.0 elif format == 'ZXY': output.x = packed / 256.0 output.y = packed / 65536.0 output.z = packed elif format == 'XYZ': output.x = packed output.y = packed / 256.0 output.z = packed / 65536.0 output.x -= math.floor(output.x) output.y -= math.floor(output.y) output.z -= math.floor(output.z) output.x = output.x*2 - 1 output.y = output.y*2 - 1 output.z = output.z*2 - 1 return output
def relocate(self, itM, o, dx, dy, alt): """ apply delta to child location """ d = archipack_custom_part.datablock(o) # child location relative to parent loc = d.pivot_location.copy() # delta location of pivot pivot = Vector() if loc.x > 0: pivot.x = dx else: pivot.x = -dx if loc.y > 0: pivot.y = dy else: pivot.y = -dy # delta for parent part loc += pivot # delta for child part # move verts so pivot remains constant in child cM = Matrix.Translation(-pivot) for v in o.data.vertices: v.co = cM * v.co # Move child so the pivot stay in same location relative to parent o.location = loc + Vector((0, 0, alt)) # store location to child data d.pivot_location = loc.copy()
def getBoundsBF(obj): """ brute force method for obtaining object bounding box """ # initialize min and max min = Vector((math.inf, math.inf, math.inf)) max = Vector((-math.inf, -math.inf, -math.inf)) # calculate min and max verts for v in obj.data.vertices: if v.co.x > max.x: max.x = v.co.x elif v.co.x < min.x: min.x = v.co.x if v.co.y > max.y: max.y = v.co.y elif v.co.y < min.y: min.y = v.co.y if v.co.z > max.z: max.z = v.co.z elif v.co.z < min.z: min.z = v.co.z # set up bounding box list of coord lists bound_box = [list(min), [min.x, min.y, min.z], [min.x, min.y, max.z], [min.x, max.y, max.z], [min.x, max.y, min.z], [max.x, min.y, min.z], [max.y, min.y, max.z], list(max), [max.x, max.y, min.z]] return bound_box
def combine_bounds(bounds: Iterable[BoundsDataStruct_YK1]) -> BoundsDataStruct_YK1: # min_pos = None # max_pos = None min_pos = Vector((-1000, -1000, -1000)) max_pos = Vector((+1000, +1000, +1000)) for bound in bounds: min_for_bound = bound.center - bound.box_extents max_for_bound = bound.center - bound.box_extents if min_pos is None: min_pos = min_for_bound max_pos = max_for_bound else: min_pos.x = min(min_for_bound.x, min_pos.x) min_pos.y = min(min_for_bound.y, min_pos.y) min_pos.z = min(min_for_bound.z, min_pos.z) max_pos.x = max(max_for_bound.x, max_pos.x) max_pos.y = max(max_for_bound.y, max_pos.y) max_pos.z = max(max_for_bound.z, max_pos.z) # TODO - This is for the sake of hierarchy objects which have no meshes themselves, but presumably have children with meshes. # Will these BBOXes need to be calculated with those other ones in mind? # Will these BBOXes need to be calculated with object position in mind? # if min_pos is None: # min_pos = Vector((0, 0, 0, 0)) # max_pos = Vector((0, 0, 0, 0)) return bounds_from_minmax(min_pos, max_pos)
def getBoundsBF(obj:Object): """ brute force method for obtaining object bounding box """ # initialize min and max min = Vector((math.inf, math.inf, math.inf)) max = Vector((-math.inf, -math.inf, -math.inf)) # calculate min and max verts for v in obj.data.vertices: if v.co.x > max.x: max.x = v.co.x elif v.co.x < min.x: min.x = v.co.x if v.co.y > max.y: max.y = v.co.y elif v.co.y < min.y: min.y = v.co.y if v.co.z > max.z: max.z = v.co.z elif v.co.z < min.z: min.z = v.co.z # set up bounding box list of coord lists bound_box = [list(min), [min.x, min.y, min.z], [min.x, min.y, max.z], [min.x, max.y, max.z], [min.x, max.y, min.z], [max.x, min.y, min.z], [max.y, min.y, max.z], list(max), [max.x, max.y, min.z]] return bound_box
def getBoundingBox(scene): minimum = Vector() maximum = Vector() for obj in scene.objects: if obj.type == 'MESH': bbox_corners = [obj.matrix_world * Vector(corner) for corner in obj.bound_box] for v in bbox_corners: if v.x < minimum.x: minimum.x = v.x if v.y < minimum.y: minimum.y = v.y if v.z < minimum.z: minimum.z = v.z if v.x > maximum.x: maximum.x = v.x if v.y > maximum.y: maximum.y = v.y if v.z > maximum.z: maximum.z = v.z return { "minimum" : { "x" : minimum.x, "y" : minimum.y, "z" : minimum.z }, "maximum" : { "x" : maximum.x, "y" : maximum.y, "z" : maximum.z } }
def calcAlign(self, localArea): alnVec = Vector([0, 0, 0]) if len(localArea) == 0: return alnVec agents = self.sim.agents for neighbour in localArea: alnVec.x += agents[neighbour].arx alnVec.y += agents[neighbour].ary alnVec.z += agents[neighbour].arz alnVec /= len(localArea) alnVec.x -= agents[self.userid].arx alnVec.y -= agents[self.userid].ary alnVec.z -= agents[self.userid].arz alnVec.x %= 2 * math.pi alnVec.y %= 2 * math.pi alnVec.z %= 2 * math.pi if alnVec.x < math.pi: alnVec.x = alnVec.x / math.pi else: alnVec.x = -2 + alnVec.x / math.pi if alnVec.y < math.pi: alnVec.y = alnVec.y / math.pi else: alnVec.y = -2 + alnVec.y / math.pi if alnVec.z < math.pi: alnVec.z = alnVec.z / math.pi else: alnVec.z = -2 + alnVec.z / math.pi return alnVec
def calcAlign(self, localArea): alnVec = Vector([0, 0, 0]) if len(localArea) == 0: return alnVec agents = self.sim.agents for neighbour in localArea: alnVec.x += agents[neighbour].arx alnVec.y += agents[neighbour].ary alnVec.z += agents[neighbour].arz alnVec /= len(localArea) alnVec.x -= agents[self.userid].arx alnVec.y -= agents[self.userid].ary alnVec.z -= agents[self.userid].arz alnVec.x %= 2*math.pi alnVec.y %= 2*math.pi alnVec.z %= 2*math.pi if alnVec.x < math.pi: alnVec.x = alnVec.x/math.pi else: alnVec.x = -2 + alnVec.x/math.pi if alnVec.y < math.pi: alnVec.y = alnVec.y/math.pi else: alnVec.y = -2 + alnVec.y/math.pi if alnVec.z < math.pi: alnVec.z = alnVec.z/math.pi else: alnVec.z = -2 + alnVec.z/math.pi return alnVec
def analyzeMeshObject(obj, meshFaces): global DEFAULT_PART_NAME mesh = obj.data parts = [] halfSize = obj.dimensions * 0.5 candidParts = [] centerOfMass = Vector((0.0, 0.0, 0.0)) trianglesCount = 0 meshVerticesCount = len(mesh.vertices) meshMaterialCount = len(mesh.materials) if meshMaterialCount > 0: # Create parts. It is important to iterate it manually # so material names order is preserved. for i in range(meshMaterialCount): candidParts.append({'name': mesh.materials[i].name, 'start': 0, 'count': 0}) else: # If there are no materials defined, create default part placeholder. candidParts.append({'name': DEFAULT_PART_NAME, 'start': 0, 'count': 0}) for f in meshFaces: # Some faces can be quads - values have to doubled then. modifier = 2 if len(f.vertices) == 4 else 1 candidParts[f.material_index]['count'] += 3 * modifier trianglesCount += 1 * modifier # Update part`s start attribute so they take other parts into account. for i in range(0, len(candidParts)): if i > 0: candidParts[i]['start'] = candidParts[i - 1]['start'] + candidParts[i - 1]['count'] # Only export parts that have any triangles assigned. for p in candidParts: if p['count'] > 0: parts.append(p) centerMax = Vector((-9999.999, -9999.999, -9999.999)) centerMin = Vector(( 9999.999, 9999.999, 9999.999)) for v in mesh.vertices: centerMax.x = max(centerMax.x, v.co.x) centerMin.x = min(centerMin.x, v.co.x) centerMax.y = max(centerMax.y, v.co.y) centerMin.y = min(centerMin.y, v.co.y) centerMax.z = max(centerMax.z, v.co.z) centerMin.z = min(centerMin.z, v.co.z) centerOfMass.x = abs(centerMax.x) - abs(centerMin.x) centerOfMass.y = abs(centerMax.y) - abs(centerMin.y) centerOfMass.z = abs(centerMax.z) - abs(centerMin.z) centerOfMass *= 0.5 return centerOfMass, halfSize, trianglesCount, parts
def calcBBPos(x, y, z, a1, a2, a3, type='DNA'): bb = Vector() if type is 'DNA': bb.x = x - (0.34 * a1.x + 0.3408 * a2.x) bb.y = y - (0.34 * a1.y + 0.3408 * a2.y) bb.z = z - (0.34 * a1.z + 0.3408 * a2.z) elif type is 'RNA': bb.x = x - (0.4 * a1.x + 0.2 * a3.x) bb.y = y - (0.4 * a1.y + 0.2 * a3.y) bb.z = z - (0.4 * a1.z + 0.2 * a3.z) return bb
def __neg__(self): """ return antipodal point """ coo=Vector() if self.co.x > 0: coo.x = self.co.x - math.pi else: coo.x = self.co.x + math.pi coo.y = abs(math.pi - self.co.y) coo.z = -self.co.z return Reflection(co=coo, normalize=False)
def __get_uv_max_min(self, loop_seqs, uv_layer): uv_max = Vector((-1000000.0, -1000000.0)) uv_min = Vector((1000000.0, 1000000.0)) for hseq in loop_seqs: for l in hseq[0]: uv = l[uv_layer].uv uv_max.x = max(uv.x, uv_max.x) uv_max.y = max(uv.y, uv_max.y) uv_min.x = min(uv.x, uv_min.x) uv_min.y = min(uv.y, uv_min.y) return uv_max, uv_min
def plank( face_vs, thickness, offset = Vector(( 0,0,0 )) ): verts = [] faces = [] if len( face_vs ) == 4: for j in range( 0,2 ): for v in face_vs: vv = Vector( v ) if j == 0: vv.x = vv.x - thickness * 0.5 else: vv.x = vv.x + thickness * 0.5 vv += offset verts.append( ( vv.x, vv.y, vv.z ) ) faces = [ (0,1,2,3), (7,6,5,4), (0,3,7,4), (0,1,5,4), (1,2,6,5), (2,3,7,6) ] elif len( face_vs ) == 7: for j in range( 0,2 ): for i in range( 0, 6 ): vv = Vector( face_vs[ i ] ) if j == 0: vv.x = vv.x - thickness * 0.5 else: vv.x = vv.x + thickness * 0.5 vv += offset verts.append( ( vv.x, vv.y, vv.z ) ) faces = [ (0,1,2,3), (3,4,5,0), (9,8,7,6), (6,11,10,9), (0,1,7,6), (1,2,8,7), (2,3,9,8), (3,4,10,9), (4,5,11,10), (5,0,6,11) ] return verts, faces
def bounding_box(mesh): v0 = mesh.vertices[0].co vmin = Vector((v0.x, v0.y, v0.z)) vmax = Vector((v0.x, v0.y, v0.z)) for i in range(1, len(mesh.vertices)): v = mesh.vertices[i].co vmin.x = min(vmin.x, v.x) vmin.y = min(vmin.y, v.y) vmin.z = min(vmin.z, v.z) vmax.x = max(vmax.x, v.x) vmax.y = max(vmax.y, v.y) vmax.z = max(vmax.z, v.z) return vmin, vmax
def execute(self, context): switchMode = False if context.mode != 'OBJECT': switchMode = True bpy.ops.object.mode_set(mode='OBJECT', toggle=True) for o in context.selected_objects: if o.type == "MESH": d = o.data m = o.matrix_world if self.center: bounds_center = (sum( (m @ Vector(b) for b in o.bound_box), Vector())) / 8 difference = m.translation - bounds_center local_difference = difference @ m for v in d.vertices: v.co += local_difference m.translation -= difference difference = Vector((0, 0, 0)) if self.side == 'X': bound = max((m @ v.co).x for v in d.vertices) difference.x = m.translation.x - bound elif self.side == '-X': bound = min((m @ v.co).x for v in d.vertices) difference.x = m.translation.x - bound elif self.side == 'Y': bound = max((m @ v.co).y for v in d.vertices) difference.y = m.translation.y - bound elif self.side == '-Y': bound = min((m @ v.co).y for v in d.vertices) difference.y = m.translation.y - bound elif self.side == 'Z': bound = max((m @ v.co).z for v in d.vertices) difference.z = m.translation.z - bound elif self.side == '-Z': bound = min((m @ v.co).z for v in d.vertices) difference.z = m.translation.z - bound local_difference = difference @ m for v in d.vertices: v.co += local_difference m.translation -= difference if self.move: o.location = context.scene.cursor.location if switchMode: bpy.ops.object.mode_set(mode='OBJECT', toggle=True) return {'FINISHED'}
def XYZ2xyY(xyz): """Converts XYZ to xyY""" xyY = Vector() # http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_xyY.html div = xyz.x + xyz.y + xyz.z if div != 0: xyY.x = xyz.x / div xyY.y = xyz.y / div else: xyY.x = D65.x / (D65.x + D65.y + D65.z) xyY.y = D65.y / (D65.x + D65.y + D65.z) xyY.z = 1.0 return xyY
def calc_box(self): if not self.verts: return Vector((0, 0, 0)), Vector((0, 0, 0)) mins = Vector(self.verts[0]) maxs = Vector(self.verts[0]) for v in self.verts: mins.x = min(mins.x, v.x) mins.y = min(mins.y, v.y) mins.z = min(mins.z, v.z) maxs.x = max(maxs.x, v.x) maxs.y = max(maxs.y, v.y) maxs.z = max(maxs.z, v.z) size = (maxs - mins) center = (maxs + mins) / 2 return size, center
def __get_island_info(uv_layer, islands): """ get information about each island """ island_info = [] for isl in islands: info = {} max_uv = Vector((-10000000.0, -10000000.0)) min_uv = Vector((10000000.0, 10000000.0)) ave_uv = Vector((0.0, 0.0)) num_uv = 0 for face in isl: n = 0 a = Vector((0.0, 0.0)) ma = Vector((-10000000.0, -10000000.0)) mi = Vector((10000000.0, 10000000.0)) for l in face['face'].loops: uv = l[uv_layer].uv ma.x = max(uv.x, ma.x) ma.y = max(uv.y, ma.y) mi.x = min(uv.x, mi.x) mi.y = min(uv.y, mi.y) a = a + uv n = n + 1 ave_uv = ave_uv + a num_uv = num_uv + n a = a / n max_uv.x = max(ma.x, max_uv.x) max_uv.y = max(ma.y, max_uv.y) min_uv.x = min(mi.x, min_uv.x) min_uv.y = min(mi.y, min_uv.y) face['max_uv'] = ma face['min_uv'] = mi face['ave_uv'] = a ave_uv = ave_uv / num_uv info['center'] = ave_uv info['size'] = max_uv - min_uv info['num_uv'] = num_uv info['group'] = -1 info['faces'] = isl info['max'] = max_uv info['min'] = min_uv island_info.append(info) return island_info
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 sRGB2linear(rgb): a = 0.055 lrgb = Vector() lrgb.x = s2lin(rgb.x) lrgb.y = s2lin(rgb.y) lrgb.z = s2lin(rgb.z) return lrgb
def calculate_bbox(verts, matrix=None): mapped_verts = verts if matrix is not None: mapped_verts = map(lambda v, M=matrix: M @ v, verts) bbox_min = Vector(next(mapped_verts)) bbox_max = bbox_min.copy() for v in mapped_verts: if v.x < bbox_min.x: bbox_min.x = v.x if v.y < bbox_min.y: bbox_min.y = v.y if v.z < bbox_min.z: bbox_min.z = v.z if v.x > bbox_max.x: bbox_max.x = v.x if v.y > bbox_max.y: bbox_max.y = v.y if v.z > bbox_max.z: bbox_max.z = v.z # Return bounding box verts return bbox_min, bbox_max
def read_vector4(io_stream): vec = Vector((0, 0, 0, 0)) vec.x = read_float(io_stream) vec.y = read_float(io_stream) vec.z = read_float(io_stream) vec.w = read_float(io_stream) return vec
def modal(self, context, event): props = context.scene.tom_props prefs = context.user_preferences.addons[__name__].preferences # 3Dビューの画面を更新 if context.area: context.area.tag_redraw() # キーボードのQキーが押された場合は、オブジェクト並進移動モードを終了 if event.type == 'Q' and event.value == 'PRESS': props.running = False print("サンプル3-10: 通常モードへ移行しました。") return {'FINISHED'} if event.value == 'PRESS': value = Vector((0.0, 0.0, 0.0)) if event.type == prefs.x_axis: value.x = 1.0 if not event.shift else -1.0 if event.type == prefs.y_axis: value.y = 1.0 if not event.shift else -1.0 if event.type == prefs.z_axis: value.z = 1.0 if not event.shift else -1.0 # 選択中のオブジェクトを並進移動する bpy.ops.transform.translate(value=value) return {'RUNNING_MODAL'}
def item_to_vector(item): """Converts XML item object to vector. SWAPS Y and Z""" v = Vector() v.x = float(item.attrib['X']) v.y = float(item.attrib['Z']) v.z = float(item.attrib['Y']) return v
def align_island_simple(obj, bm, uv_layers, faces, x=0, y=1, flip_x=False, flip_y=False): # Find lowest and highest verts minmax_val = [0, 0] minmax_vert = [None, None] axis_names = ['x', 'y', 'z'] print("Align shell {}x at {},{} flip {},{}".format( len(faces), axis_names[x], axis_names[y], flip_x, flip_y)) # Collect UV to Vert vert_to_uv = {} face = faces[0] for loop in face.loops: vert = loop.vert uv = loop[uv_layers] vert_to_uv[vert] = [uv] uv.select = True edge = faces[0].edges[0] delta = edge.verts[0].co - edge.verts[1].co max_side = max(abs(delta.x), abs(delta.y), abs(delta.z)) # Check edges dominant in active axis if abs(delta[x]) == max_side or abs(delta[y]) == max_side: uv0 = vert_to_uv[edge.verts[0]][0] uv1 = vert_to_uv[edge.verts[1]][0] delta_verts = Vector((edge.verts[1].co[x] - edge.verts[0].co[x], edge.verts[1].co[y] - edge.verts[0].co[y])) if flip_x: delta_verts.x = -edge.verts[1].co[x] + edge.verts[0].co[x] if flip_y: delta_verts.y = -edge.verts[1].co[y] + edge.verts[0].co[y] delta_uvs = Vector((uv1.uv.x - uv0.uv.x, uv1.uv.y - uv0.uv.y)) a0 = math.atan2(delta_verts.y, delta_verts.x) a1 = math.atan2(delta_uvs.y, delta_uvs.x) a_delta = math.atan2(math.sin(a0 - a1), math.cos(a0 - a1)) print("Turn {:.1f}".format(a_delta * 180 / math.pi)) bpy.ops.uv.select_all(action='DESELECT') for face in faces: for loop in face.loops: loop[uv_layers].select = True bpy.context.tool_settings.transform_pivot_point = 'MEDIAN_POINT' bpy.ops.transform.rotate( value=-a_delta, orient_axis='Z' ) # minus angle; Blender uses unconventional rotation notation (positive for clockwise)
def saveVertex(fh, fnormal, useSmooth, uvLayer, vtx, vInx, ofst, exportType): uv = Vector((0.0, 1.0)) normal = Vector((fnormal.x, fnormal.y, fnormal.z)) weights = (0.0, 0.0, 0.0, 0.0) co = vtx.co - ofst if uvLayer != None: uv.x = uvLayer.uv_raw[vInx * 2 + 0] uv.y = -uvLayer.uv_raw[vInx * 2 + 1] if useSmooth: normal = vtx.normal rotationMatrix = Matrix.Rotation(math.radians(-90.0), 3, "X") co = rotationMatrix * co normal = rotationMatrix * normal if exportType == eTypes.TYPE0: saveVertexType0(fh, co, uv) elif exportType == eTypes.TYPE1: saveVertexType1(fh, co, normal, uv) elif exportType == eTypes.TYPE2: saveVertexType2(fh, co, normal, uv, weights) elif exportType == eTypes.TYPE3: saveVertexType3(fh, co, normal, uv) elif exportType == eTypes.TYPE4: saveVertexType4(fh, co, normal, uv, weights)
def modal(self, context, event): props = context.scene.tom_props # @include-source start [get_prefs] prefs = context.user_preferences.addons[__name__].preferences # @include-source end [get_prefs] # 3Dビューの画面を更新 if context.area: context.area.tag_redraw() # キーボードのQキーが押された場合は、オブジェクト並進移動モードを終了 if event.type == 'Q' and event.value == 'PRESS': props.running = False print("サンプル3-10: 通常モードへ移行しました。") return {'FINISHED'} # @include-source start [refer_prefs] if event.value == 'PRESS': value = Vector((0.0, 0.0, 0.0)) if event.type == prefs.x_axis: value.x = 1.0 if not event.shift else -1.0 if event.type == prefs.y_axis: value.y = 1.0 if not event.shift else -1.0 if event.type == prefs.z_axis: value.z = 1.0 if not event.shift else -1.0 # 選択中のオブジェクトを並進移動する bpy.ops.transform.translate(value=value) # @include-source end [refer_prefs] return {'RUNNING_MODAL'}
def compute_mesh_bounds(mesh): from mathutils import Vector inf = 1.192092896e-07 min = Vector((inf, inf, inf)) max = Vector((-inf, -inf, -inf)) for i, v in enumerate(mesh.vertices): lowx = min.x; lowy = min.y; lowz = min.z; hix = max.x; hiy = max.y; hiz = max.z; vec = Vector(v.co[:]) vec.x = -vec.x if vec.x < lowx: lowx = vec.x if vec.y < lowy: lowy = vec.y if vec.z < lowz: lowz = vec.z if vec.x > hix: hix = vec.x if vec.y > hiy: hiy = vec.y if vec.z > hiz: hiz = vec.z min = Vector((lowx, lowy, lowz)) max = Vector((hix, hiy, hiz)) return { "min": min, "max": max }
def viewDir(dis_v, ang_v): """Converts Distance and Angle to View Oriented Vector. Converts View Transformation Matrix to Rotational Matrix (3x3) Angles are converted to Radians from degrees. Args: dis_v: Scene distance ang_v: Scene angle Returns: World Vector. """ areas = [a for a in bpy.context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: vm = areas[0].spaces.active.region_3d.view_matrix vm = vm.to_3x3().normalized().inverted() vl = Vector((0, 0, 0)) vl.x = dis_v * cos(ang_v * pi / 180) vl.y = dis_v * sin(ang_v * pi / 180) vw = vm @ vl return vw else: return Vector((0, 0, 0))
def modal(self, context, event): props = context.scene.tom_props # 3Dビューの画面を更新 if context.area: context.area.tag_redraw() # キーボードのQキーが押された場合は、オブジェクト並進移動モードを終了 if event.type == 'Q' and event.value == 'PRESS': props.running = False print("サンプル3-2: 通常モードへ移行しました。") return {'FINISHED'} if event.value == 'PRESS': value = Vector((0.0, 0.0, 0.0)) if event.type == 'X': value.x = 1.0 if not event.shift else -1.0 if event.type == 'Y': value.y = 1.0 if not event.shift else -1.0 if event.type == 'Z': value.z = 1.0 if not event.shift else -1.0 # 選択中のオブジェクトを並進移動する bpy.ops.transform.translate(value=value) return {'RUNNING_MODAL'}
def relocate(context, isVertical, padding, all_ob_bounds, ob_num=0): if ob_num > 0: if len(all_ob_bounds[ob_num]) > 0: offset = 0.0 origin = Vector((0, 0)) for i in range(0, ob_num): if len(all_ob_bounds[i]) > 0: if isVertical: offset += all_ob_bounds[i]['height'] + padding else: offset += all_ob_bounds[i]['width'] + padding for i in range(0, ob_num + 1): if len(all_ob_bounds[i]) > 0: origin.x = all_ob_bounds[i]['min'].x origin.y = all_ob_bounds[i]['max'].y break delta = Vector((origin.x - all_ob_bounds[ob_num]['min'].x, origin.y - all_ob_bounds[ob_num]['max'].y)) if isVertical: bpy.ops.transform.translate(value=(delta.x, delta.y - offset, 0)) else: bpy.ops.transform.translate(value=(delta.x + offset, delta.y, 0))
def view_dir(dis_v, ang_v): """Converts Distance and Angle to View Oriented Vector. Note: Converts View Transformation Matrix to Rotational Matrix (3x3) Angles are Converts to Radians from degrees. Args: dis_v: Scene PDT distance ang_v: Scene PDT angle Returns: World Vector. """ areas = [a for a in bpy.context.screen.areas if a.type == "VIEW_3D"] if len(areas) > 0: view_matrix = areas[0].spaces.active.region_3d.view_matrix view_matrix = view_matrix.to_3x3().normalized().inverted() view_location = Vector((0, 0, 0)) view_location.x = dis_v * cos(ang_v * pi / 180) view_location.y = dis_v * sin(ang_v * pi / 180) new_view_location = view_matrix @ view_location return new_view_location return Vector((0, 0, 0))
def update(self, ctx, clickcount, dimantion): dim = dimantion if self.shift: index = -1 if len(self.subclass.knots) < 2 else -2 lastpoint = self.subclass.knots[index].pos dim.view = get_axis_constraint(lastpoint, dim.view) if self.drag: pos = self.subclass.knots[-1].pos outvec = dim.view invec = Vector((0,0,0)) invec.x = pos.x - (outvec.x - pos.x) invec.y = pos.y - (outvec.y - pos.y) invec.z = pos.z - (outvec.z - pos.z) newknot = knot(pos, invec, outvec, 'ALIGNED') else: newknot = knot(dim.view, dim.view, dim.view, "VECTOR") if clickcount != self.lastclick: self.subclass.knots.append(newknot) self.lastclick = clickcount check_for_close(self, ctx) if LineData.close: self.subclass.knots.pop() self.subclass.close = True self.forcefinish = True self.subclass.knots[-1] = newknot self.subclass.lastknot = [knot(dim.view, dim.view, dim.view, "VECTOR")] self.subclass.update(ctx)
def find_HalfExtent_scale(loc): scale = Vector() values = loc.find("*[@Name='HalfExtents']").attrib scale.x = float(values['X']) scale.y = float(values['Z']) scale.z = float(values['Y']) return scale
def pointInIsland(pt, island): vec1, vec2, vec3 = Vector(), Vector(), Vector() for f in island: vec1.x, vec1.y = f.uv[0] vec2.x, vec2.y = f.uv[1] vec3.x, vec3.y = f.uv[2] if pointInTri2D(pt, vec1, vec2, vec3): return True if len(f.v) == 4: vec1.x, vec1.y = f.uv[0] vec2.x, vec2.y = f.uv[2] vec3.x, vec3.y = f.uv[3] if pointInTri2D(pt, vec1, vec2, vec3): return True return False
def saveVertex(fh, obj, fnormal, useSmooth, uvLayer, vtx, vInx): uv = Vector((0.0, 1.0)) normal = Vector((fnormal.x, fnormal.y, fnormal.z)) weights = (0.0, 0.0, 0.0, 0.0) co = obj.location + vtx.co; co.x = -co.x if uvLayer != None: uv.x = uvLayer.uv_raw[vInx * 2 + 0] uv.y = -uvLayer.uv_raw[vInx * 2 + 1] if useSmooth: normal = vtx.normal normal.x = -normal.x saveVertexType4(fh, co, normal, uv, weights)
def gui_space(p): p = Vector(p).copy() p.x = p.x*16 - 8 p.y = p.y*9 - 4.5 p.y *= -1 return p
def shade(self, stroke): it = stroke.stroke_vertices_begin() if it.is_end: return p_min = it.object.point.copy() p_max = it.object.point.copy() while not it.is_end: p = it.object.point if p.x < p_min.x: p_min.x = p.x if p.x > p_max.x: p_max.x = p.x if p.y < p_min.y: p_min.y = p.y if p.y > p_max.y: p_max.y = p.y it.increment() stroke.resample(32 * self.__turns) sv_nb = stroke.stroke_vertices_size() # print("min :", p_min.x, p_min.y) # DEBUG # print("mean :", p_sum.x, p_sum.y) # DEBUG # print("max :", p_max.x, p_max.y) # DEBUG # print("----------------------") # DEBUG ####################################################### sv_nb = sv_nb // self.__turns center = (p_min + p_max) / 2 radius = (center.x - p_min.x + center.y - p_min.y) / 2 p_new = Vector((0.0, 0.0)) ####################################################### R = self.__random_radius C = self.__random_center i = 0 it = stroke.stroke_vertices_begin() for j in range(self.__turns): prev_radius = radius prev_center = center radius = radius + randint(-R, R) center = center + Vector((randint(-C, C), randint(-C, C))) while i < sv_nb and not it.is_end: t = float(i) / float(sv_nb - 1) r = prev_radius + (radius - prev_radius) * t c = prev_center + (center - prev_center) * t p_new.x = c.x + r * cos(2 * pi * t) p_new.y = c.y + r * sin(2 * pi * t) it.object.point = p_new i = i + 1 it.increment() i = 1 verticesToRemove = [] while not it.is_end: verticesToRemove.append(it.object) it.increment() for sv in verticesToRemove: stroke.remove_vertex(sv) stroke.update_length()
def __get_island_info(self, uv_layer, islands): """ get information about each island """ island_info = [] for isl in islands: info = {} max_uv = Vector((-10000000.0, -10000000.0)) min_uv = Vector((10000000.0, 10000000.0)) ave_uv = Vector((0.0, 0.0)) num_uv = 0 for face in isl: n = 0 a = Vector((0.0, 0.0)) for l in face['face'].loops: uv = l[uv_layer].uv if uv.x > max_uv.x: max_uv.x = uv.x if uv.y > max_uv.y: max_uv.y = uv.y if uv.x < min_uv.x: min_uv.x = uv.x if uv.y < min_uv.y: min_uv.y = uv.y a = a + uv n = n + 1 ave_uv = ave_uv + a num_uv = num_uv + n a = a / n face['ave_uv'] = a ave_uv = ave_uv / num_uv info['center'] = ave_uv info['size'] = max_uv - min_uv info['num_uv'] = num_uv info['group'] = -1 info['faces'] = isl island_info.append(info) return island_info
def roi2point(self, msg): """ Returns a normalized point at the center of the given RegionOfInterest message. """ p = Vector([0,0,0]) if self.camerainfo.width > 0: p.x = 0.5 - (msg.x_offset+(msg.width/2.0))/self.camerainfo.width if self.camerainfo.height > 0: p.z = 0.5 - (msg.y_offset+(msg.height/2.0))/self.camerainfo.height return p
def getDimensions(self): highest = Vector((-10000, -10000, -10000)) lowest = Vector(( 10000, 10000, 10000)) for bone in self.bones: if highest.x < bone.restHead.x: highest.x = bone.restHead.x if highest.y < bone.restHead.y: highest.y = bone.restHead.y if highest.z < bone.restHead.z: highest.z = bone.restHead.z if highest.x < bone.restTail.x: highest.x = bone.restTail.x if highest.y < bone.restTail.y: highest.y = bone.restTail.y if highest.z < bone.restTail.z: highest.z = bone.restTail.z if lowest .x > bone.restHead.x: lowest .x = bone.restHead.x if lowest .y > bone.restHead.y: lowest .y = bone.restHead.y if lowest .z > bone.restHead.z: lowest .z = bone.restHead.z if lowest .x > bone.restTail.x: lowest .x = bone.restTail.x if lowest .y > bone.restTail.y: lowest .y = bone.restTail.y if lowest .z > bone.restTail.z: lowest .z = bone.restTail.z return Vector((highest.x - lowest.x, highest.y - lowest.y, highest.z - lowest.z))
def _move(self, direction, value): """ Moves view into direction by value. """ for view in self.get3DView(): offset = Vector((0.0, 0.0, 0.0)) if direction == "horizontal": offset.x = value elif direction == "vertical": offset.y = value elif direction == "straightforward": offset.z = value view.view_location = view.view_rotation*offset + view.view_location
def staticAvoidanceVector(self,playerPos): '''find an avoidance vector for static objects in scene Parameters: playerPos -- the 3D Vector of the player's position Returns: 2D Vector describing a way to avoid the static objects in the scene (fences, houses, trees,...) ''' p1 = playerPos.copy() p1.z = 0 result = Vector((0,0,0)) for v in self.obstacles: p2 = v.copy() p2.z = 0 dist = (p1 - p2).magnitude angle = atan2(p1.y - p2.y,p1.x - p2.x) if 0 < dist < 2*self.r1: size = 2/dist**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) for v in self.bigObstacles: p2 = v.copy() p2.z = 0 dist = (p1 - p2).magnitude angle = atan2(p1.y - p2.y,p1.x - p2.x) if 3*self.r1 < dist < 6*self.r1: size = 2/(dist-2*self.r1)**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) elif self.r1 < dist <= 3*self.r1: size = 2/dist**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) elif dist < self.r1: size = 10/dist**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) for v in self.fences: p2 = v.copy() p2.z = 0 dist = (p1 - p2).magnitude angle = atan2(p1.y - p2.y,p1.x - p2.x) if self.r1 < dist < 3*self.r1: size = 2/dist**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) elif 0 < dist <= self.r1: size = 10/dist**2 result.x = result.x + size*cos(angle) result.y = result.y + size*sin(angle) return Vector((result.x,result.y))
def execute(self, context): scene = context.scene obj = context.active_object # check if active object is a mesh object if not obj or obj.type != 'MESH': self.report({'ERROR'}, "No selected mesh object!") return {'CANCELLED'} # check if it has one single face if len(obj.data.polygons) != 1: self.report({'ERROR'}, "The selected mesh object has to have exactly one quad!") return {'CANCELLED'} rl = scene.lightfield.row_length # use a degree angle here angle = degrees(scene.lightfield.angle) spacing = scene.lightfield.spacing # resolution of final renderings res = round(scene.render.resolution_x * (scene.render.resolution_percentage / 100.)) width = self.getWidth(obj) # the offset between n pixels on the focal plane fplane_offset = (width / res) * spacing # vertices for the basemesh verts = [] # the offset vector vec = self.getCamVec(obj, angle) # lower left coordinates of the grid sx = obj.location[0] - fplane_offset * int(rl / 2) sy = obj.location[1] - fplane_offset * int(rl / 2) z = obj.location[2] # position on the focal plane fplane_pos = Vector() for x in [sx + fplane_offset * i for i in range(rl)]: for y in [sy + fplane_offset * i for i in range(rl)]: fplane_pos.x = x fplane_pos.y = y fplane_pos.z = z # position of a vertex in a basemesh pos = fplane_pos + vec # pack coordinates flat into the vert list verts.append((pos.x, pos.y, pos.z)) # setup the basemesh and add verts mesh = bpy.data.meshes.new(self.objName) mesh.from_pydata(verts, [], []) self.addMeshObj(mesh) return {'FINISHED'}
def Translate(mesh, vtx_weight_dict, shapekey_out, dx, dy, dz): # Purpose: translate vertices in the weight dict somewhere verts = shapekey_out.data vwd = vtx_weight_dict d = Vector((0,0,0)) for i in range(len(verts)): if i in vwd: d.x = dx d.y = dy d.z = dz verts[i].co += vwd[i] * d else: continue
def get_motion_range(cls, obj): """Returns a range vector giving the frame range in which the object has motion """ range = Vector((1000000, -1000000)) while obj: if obj.animation_data and obj.animation_data.action: range.x = min(range.x, obj.animation_data.action.frame_range[0]) range.y = max(range.y, obj.animation_data.action.frame_range[1]) obj = obj.parent return range
def __get_x_axis_align_diff_uvs(self, loop_seqs, uv_layer, uv_min, width, height): diff_uvs = [] for hidx, hseq in enumerate(loop_seqs): pair = hseq[0] luv0 = pair[0][uv_layer] luv1 = pair[1][uv_layer] target_uv0 = Vector((0.0, 0.0)) target_uv1 = Vector((0.0, 0.0)) if self.location == 'RIGHT_BOTTOM': target_uv0.y = target_uv1.y = uv_min.y elif self.location == 'MIDDLE': target_uv0.y = target_uv1.y = uv_min.y + height * 0.5 elif self.location == 'LEFT_TOP': target_uv0.y = target_uv1.y = uv_min.y + height if luv0.uv.x < luv1.uv.x: target_uv0.x = uv_min.x + hidx * width / len(loop_seqs) target_uv1.x = uv_min.x + (hidx + 1) * width / len(loop_seqs) else: target_uv0.x = uv_min.x + (hidx + 1) * width / len(loop_seqs) target_uv1.x = uv_min.x + hidx * width / len(loop_seqs) diff_uvs.append([target_uv0 - luv0.uv, target_uv1 - luv1.uv]) return diff_uvs
def position_frame_bottom_left(node_tree, frame_node): newpos = Vector((100000, 100000)) # start reasonably far top / right # Align with the furthest left for node in node_tree.nodes.values(): if node != frame_node and node.parent != frame_node: newpos.x = min(newpos.x, node.location.x + 30) # As high as we can get without overlapping anything to the right for node in node_tree.nodes.values(): if node != frame_node and not node.parent: if node.location.x < newpos.x + frame_node.width: print("Below", node.name, node.location, node.height, node.dimensions) newpos.y = min(newpos.y, node.location.y - max(node.dimensions.y, node.height) - 20) frame_node.location = newpos
def calcBranch(self, branch, angle=0): rotation = uniform(0, pi * 2) br = copy(branch) a = br.a o = Vector([uniform(-1,1),uniform(-1,1),uniform(-1,1)]) if a.x != 0: o.x = -(a.y * o.y + a.z * o.z) / a.x elif a.y != 0: o.y = -(a.x * o.x + a.z * o.z) / a.y elif a.z != 0: o.z = -(a.x * o.x + a.y * o.y) / a.z else: raise Exception("Invalid input: zero vector") o = norm(o) assert(inner_product(o) > .9999 or inner_product(o) < 1.0001) assert(o * a < 0.0001) br.a = rotation_mat(branch.a, rotation) * (rotation_mat(o, angle) * br.a) br.a = norm(vec_vec_mult(br.a, self.gradual_angle)) return br
def resize_primary_brush(self, radius): context = bpy.context primary_brush = self.primary_brush region_height = context.region.height region_width = context.region.width # Determine the world space radius of the primary brush necessary to # project a circle onto the view plane with the specified region space # radius. # Determine the z-depth of the primary brush's center in normalized # device coordinates. projection_matrix = context.region_data.perspective_matrix co = primary_brush.center.copy() co.resize(4) co.w = 1 co.xyzw = projection_matrix * co w = co.w co.xyz /= w NDC_z_depth = co.z # Determine the region space coordinates of the primary brush's center. region_x = (co.x + 1) * region_width / 2 region_y = (co.y + 1) * region_height / 2 # Determine the NDC coordinates of a point on the edge of the # circle that should result from projecting the brush onto the view # plane. co = Vector((region_x, region_y)) + Vector((radius, 0)) co.x = co.x * 2 / region_width - 1 co.y = co.y * 2 / region_height - 1 co.resize(3) co.z = NDC_z_depth # Calculate the world space radius of the primary brush. co.resize(4) co.w = 1 co.xyzw = projection_matrix.inverted() * co w = co.w co.resize(3) co.xyz /= w primary_brush.radius = (co - primary_brush.center).length
def apply_location(self, user): for joint in user.joints.values(): for obj in bpy.data.objects: if obj.type != "ARMATURE": continue armature = obj if not armature.pose: continue pose = armature.pose if not pose.bones: continue bones = pose.bones if joint.name not in bones: continue bone = bones[joint.name] if not bone: continue location = Vector() location.x = joint.location.x location.y = joint.location.y location.z = joint.location.z parent = bone while not hasattr(parent, "parent"): parent = parent.parent if not parent: continue if not hasattr(parent, "location"): continue location.x -= parent.location.x location.y -= parent.location.y location.z -= parent.location.z bone.location = location if bpy.amk2b.recording_started: bone.keyframe_insert(data_path="location", frame=bpy.context.scene.frame_current)
def update(self): x, y = logic.mouse.position cam = self.obj pos = Vector([0,0,0]) m = self.margin n = self.capmargin l = 1 speed = self.speed * cam.worldPosition.z if y < m: pos.y -= speed if y < n: y = n if y > 1-m: pos.y += speed if y > 1-n: y = 1-n if x < m: pos.x -= speed if x < n: x = n if x > 1-m: pos.x += speed if x > 1-n: x = 1-n logic.mouse.position = (x, y) rot = cam.worldOrientation.to_euler() x, y = (pos.x, pos.y) pos.x = x * math.cos(rot.z) + y * math.cos(rot.z-1.5) pos.y = x * math.sin(rot.z) + y * math.sin(rot.z-1.5) cam.worldPosition = pos + cam.worldPosition