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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 getRandomLoc(randomLoc, rand, width, height): """ get random location between (0,0,0) and (width/2, width/2, height/2) """ loc = Vector((0, 0, 0)) loc.xy = [rand.uniform(-(width / 2) * randomLoc, (width / 2) * randomLoc)] * 2 loc.z = rand.uniform(-(height / 2) * randomLoc, (height / 2) * randomLoc) return loc
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 find_xyz(loc, valname): """returns vector named valname in loc""" v = Vector() values = loc.find(f"*[@Name='{valname}']").attrib v.x = float(values['X']) v.y = float(values['Z']) v.z = float(values['Y']) return v
def find_xyz_from_mat(loc, mat_name): """returns xyz from matrix named mat_name in loc""" a = Vector() values = loc.find(f"*[@Name='{mat_name}']").attrib a.x = float(values['M41']) a.y = float(values['M43']) a.z = float(values['M42']) return a
def fencehop(): cont = bge.logic.getCurrentController() own = cont.owner auto_action = cont.sensors['auto_action'] if not auto_action: return False elif own['isSpaceon']: #Gather info on the fence fence_obj = auto_action.hitObject fence_pos = fence_obj.worldPosition #get the normal of the fence hit_norm = Vector(auto_action.hitNormal) hit_norm.z = 0.0 #Vector axis of Sintel own_negative_y = Vector(own.getAxisVect((0.0, -1.0, 0.0))) own_negative_y.z = 0.0 #Cross it, then get the absolute vaule cross = hit_norm.cross(own_negative_y) cross = math.fabs(cross[2]) #print (cross) #Check the angle of approach if cross <=.5: new_pos = (fence_pos[2] + 2) own.worldPosition[2] = new_pos own['Leaping']=True CURRENT_SPEED = own.getLinearVelocity(True) if CURRENT_SPEED[1] < 11: CURRENT_SPEED[1] = 11 CURRENT_SPEED[2] = 10 #print (CURRENT_SPEED) own.setLinearVelocity(CURRENT_SPEED ,True) own['Tracking']=False return True else: return False
def get_min_max(vertList): min = Vector(vertList[0]) max = Vector(vertList[0]) for v in vertList: if v.x < min.x: min.x = v.x elif v.x > max.x: max.x = v.x if v.y < min.y: min.y = v.y elif v.y > max.y: max.y = v.y if v.z < min.z: min.z = v.z elif v.z > max.z: max.z = v.z return min, max
def fencehop(): cont = bge.logic.getCurrentController() own = cont.owner auto_action = cont.sensors['auto_action'] if not auto_action: return False elif own['isSpaceon']: #Gather info on the fence fence_obj = auto_action.hitObject fence_pos = fence_obj.worldPosition #get the normal of the fence hit_norm = Vector(auto_action.hitNormal) hit_norm.z = 0.0 #Vector axis of Sintel own_negative_y = Vector(own.getAxisVect((0.0, -1.0, 0.0))) own_negative_y.z = 0.0 #Cross it, then get the absolute vaule cross = hit_norm.cross(own_negative_y) cross = math.fabs(cross[2]) #print (cross) #Check the angle of approach if cross <= .5: new_pos = (fence_pos[2] + 2) own.worldPosition[2] = new_pos own['Leaping'] = True CURRENT_SPEED = own.getLinearVelocity(True) if CURRENT_SPEED[1] < 11: CURRENT_SPEED[1] = 11 CURRENT_SPEED[2] = 10 #print (CURRENT_SPEED) own.setLinearVelocity(CURRENT_SPEED, True) own['Tracking'] = False return True else: return False
def onKeyPressed(self, keys): rot = self.obj.worldOrientation.to_euler() pos = Vector([0, 0, 0]) if key.W in keys: rot.x += 0.01 if key.S in keys: rot.x -= 0.01 if key.A in keys: rot.z += 0.01 if key.D in keys: rot.z -= 0.01 if key.WHEELUPMOUSE in keys: pos.z = -self.obj.worldPosition.z * 0.3 if key.WHEELDOWNMOUSE in keys: pos.z = self.obj.worldPosition.z * 0.3 #Max speed is dependent of the Tile sizes, ex (200m/s = size) / 50fps = 4m/tick #Since we are using an extra radius we can guarante a speed of 8m/tick without glitches: 8*60fps = 480m/s = 1728 km/h #if pos.length > 8: pos.length = 8 #But we don't care for now if pos.length > 50: pos.length = 50 pos.rotate(self.obj.worldOrientation) self.obj.worldPosition += pos self.obj.worldOrientation = rot
def onKeyPressed(self, keys): rot = self.obj.worldOrientation.to_euler() pos = Vector([0,0,0]) if key.W in keys: rot.x += 0.01 if key.S in keys: rot.x -= 0.01 if key.A in keys: rot.z += 0.01 if key.D in keys: rot.z -= 0.01 if key.WHEELUPMOUSE in keys: pos.z = -self.obj.worldPosition.z * 0.3 if key.WHEELDOWNMOUSE in keys: pos.z = self.obj.worldPosition.z * 0.3 #Max speed is dependent of the Tile sizes, ex (200m/s = size) / 50fps = 4m/tick #Since we are using an extra radius we can guarante a speed of 8m/tick without glitches: 8*60fps = 480m/s = 1728 km/h #if pos.length > 8: pos.length = 8 #But we don't care for now if pos.length > 50: pos.length = 50 pos.rotate(self.obj.worldOrientation) self.obj.worldPosition += pos self.obj.worldOrientation = rot
def get_max(ob): mx = Vector((-1000., -1000., -1000.)) for vx in ob.data.vertices: p = ob.matrix_world * vx.co mx.x = max(mx.x, p.x) mx.y = max(mx.y, p.y) mx.z = max(mx.z, p.z) return mx
def processCamera(cont): own = cont.owner axis = own.childrenRecursive["CameraAxis"] own.scene.active_camera.timeOffset = CAMERA_SMOOTH posVector = Vector((0, 0, 0)) if own["Landing"]: posVector.y = VIEW_HEIGHT_DISTANCE * 3 posVector.z = VIEW_HEIGHT_DISTANCE else: posVector.z = -VIEW_HEIGHT_DISTANCE if own["DirectionH"] == "Left": posVector.x = -VIEW_AHEAD_DISTANCE elif own["DirectionH"] == "Right": posVector.x = VIEW_AHEAD_DISTANCE axis.worldPosition = own.worldPosition + posVector
def get_all_max_min(): min_p = Vector([float('inf'), float('inf'), float('inf')]) max_p = Vector([-float('inf'), -float('inf'), -float('inf')]) for obj in bpy.data.objects: if obj.type != 'MESH': continue max_min = get_object_max_min(obj) # Max max_p.x = max(max_p.x, max_min['max'].x) max_p.y = max(max_p.y, max_min['max'].y) max_p.z = max(max_p.z, max_min['max'].z) # Min min_p.x = min(min_p.x, max_min['min'].x) min_p.y = min(min_p.y, max_min['min'].y) min_p.z = min(min_p.z, max_min['min'].z) return { 'min': min_p, 'max': max_p }
def get_random_loc(random_loc, rand, half_width, half_height): """ get random location between (0,0,0) and (width/2, width/2, height/2) """ loc = Vector((0, 0, 0)) if random_loc > 0: loc.xy = [ rand.uniform(-half_width * random_loc, half_width * random_loc) ] * 2 loc.z = rand.uniform(-half_height * random_loc, half_height * random_loc) return loc
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 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 read_vector_axis_vecteur(node): v = Vector((0.0, 0.0, 0.0)) childs = node.getElementsByTagName('x') if childs: v.x = ret_float_value(childs[0]) childs = node.getElementsByTagName('y') if childs: v.y = ret_float_value(childs[0]) childs = node.getElementsByTagName('z') if childs: v.z = ret_float_value(childs[0]) return v
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 main(): cont = bge.logic.getCurrentController() own = cont.owner wall_ray = cont.sensors["wall_ray"] wall_normal = Vector(wall_ray.hitNormal) wall_normal.z = 0.0 own_negative_y = Vector(own.getAxisVect((0.0, -1.0, 0.0))) own_negative_y.z = 0.0 cross = wall_normal.cross(own_negative_y) if cross.z > 0.0: new_dir = Matrix.Rotation(-90.0, 3, 'X') * wall_normal else: new_dir = Matrix.Rotation(90.0, 3, 'X') * wall_normal #print (new_dir) #own.alignAxisToVect(new_dir, 0, .1)
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 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 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 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 _frames_difference_vector(self, frames, attr_func): """ Calculates the difference Vector of attribute on the first and the last frame. """ res = Vector((0.0, 0.0, 0.0)) for i in (0, -1): #get attributes from frames[i] v = attr_func(frames[i]) if i == 0: res.y -= v.y res.x -= v.x res.z -= v.z else: res.y += v.y res.x += v.x res.z += v.z if res.x > settings.max_x and res.x < -settings.max_x: res.y = 0 if res.y > settings.max_y and res.y < -settings.max_y: res.y = 0 if res.z > settings.max_z and res.z < -settings.max_z: res.z = 0 return res
def execute(self, context): scene = context.scene sp = scene.speaker scene_objects_set = set(scene.objects) obj = context.active_object # copy cursor location cursor_loc = scene.cursor_location.copy() # snap the cursor to the selected bpy.ops.view3d.snap_cursor_to_selected() channels = self.rows * self.cols # bpy.context for testing. Use context from Op, Panel method. originals = context.selected_objects.copy() # has the selected objects in it. c = {} c["scene"] = scene c["screen"] = context.screen c["area"] = context.area c["region"] = context.region c["active_object"] = None c["edit_object"] = None c["window"] = context.window # c["selected_bases"] = context.selected_bases.copy() # c["selected_editable_objects"] = context.selected_editable_objects.copy() # c["selected_bases"] = [] c["selected_objects"] = originals dimensions = bbdim(selected_bbox(context)) # Location of original unit location = scene.cursor_location.copy() st_handle = bpy.data.objects.new("ST_handle", None) st_handle["channels"] = channels scene.objects.link(st_handle) st_handle.matrix_world.translation = location st_handle["ST_Vis"] = 0 handles = [] new_objects = set(originals) vis = [] # make duplicates for i in range(channels): scene.update() handle = bpy.data.objects.new("ch[%04d]" % i, None) scene.objects.link(handle) handle["ST_Vis"] = i # the channel to drive with. handle.parent = st_handle handles.append(handle) # make the handle the objects parent if no parent else if i: scene_objects_set = set(scene.objects) bpy.ops.object.duplicate(c, 'INVOKE_DEFAULT', linked=False) scene.update() new_objects = set(scene.objects) - scene_objects_set vis.append((i, handle, new_objects)) for i, handle, new_objects in vis: for o in new_objects: print(o, o.parent) if not o.parent or o.parent in handles: o.parent = handle if not i or not o.animation_data: continue # drivers ok for ch0 # get the drivers of o # have speaker as a var target # have CH0 as a variable drivers = o.animation_data.drivers drivers = [d for d in drivers for v in d.driver.variables for t in v.targets if t.id == sp] for d in drivers: all_channels, args = get_driver_settings(d) driver = d.driver expr = driver.expression for ch in all_channels: if len(ch) == 3 and ch.endswith("0"): all_channels.remove(ch) newch = ch.replace("0", str(i)) expr = expr.replace(ch, newch) all_channels.append(newch) var = driver.variables.get(ch) var.name = newch var.targets[0].data_path = var.targets[0].data_path.replace(ch, newch) driver.expression = driver_expr(expr, all_channels, args) # distribute # Properties rows = self.rows cols = self.cols offset = Vector(self.offset) offset.x = dimensions.x * offset.x offset.y = dimensions.y * offset.y offset.z = dimensions.z * offset.z # deselect all bpy.ops.object.select_all(action='DESELECT') self.handle = st_handle is not None self.handle_name = st_handle.name context.scene.objects.active = st_handle st_handle.select = True st_handle["VIS"] = 'GRID' # make an rna and make a grid vis_RNA = { "name": self.handle_name, "rows": self.rows, "cols": self.cols, "channels": channels, "offset": { "x": self.offset[0], "y": self.offset[1], "z": self.offset[2] }, "dimensions": { "x": dimensions[0], "y": dimensions[1], "z": dimensions[2], } } st_handle['_RNA_UI'] = {} st_handle['_RNA_UI']["VIS"] = vis_RNA # make a new edit item in the grids collection grid = context.scene.visualisers.grids.add() grid.name = st_handle.name grid.rows = self.rows grid.cols = self.cols grid.offset = self.offset return {'FINISHED'}
# キーボードのQキーが押された場合は、オブジェクト並進移動モードを終了 if event.type == 'Q' and event.value == 'PRESS': props.running = False print("サンプル3-10: 通常モードへ移行しました。") return {'FINISHED'} //! [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) //! [refer_prefs] return {'RUNNING_MODAL'} def invoke(self, context, event): props = context.scene.tom_props if context.area.type == 'VIEW_3D': # 開始ボタンが押された時の処理 if props.running is False: props.running = True # modal処理クラスを追加 context.window_manager.modal_handler_add(self) print("サンプル3-2: オブジェクト並進移動モードへ移行しました。")
def scan(numberOfRays, max_distance, elementsPerRay, keep_render_setup, do_shading, rays_buffer, returns_buffer, ELEMENTS_PER_RETURN): if ELEMENTS_PER_RETURN != 8: raise Exception("Scan interface incompatible") # Step 1: Scene to polygons / store face indices and materials tris = [] faces = [] face_array,obj_array,mat_array = scene_to_mesh() for idx,f in enumerate(face_array): tris.append(list(f[0])) tris.append(list(f[1])) tris.append(list(f[2])) faces.append([idx*3,idx*3+1,idx*3+2]) # Step 2: Polygons to BVH tree scene_bvh = BVHTree.FromPolygons(tris, faces, all_triangles = True) # Step 3: Raycast rays scanner = bpy.context.scene.camera reflectivity_distance = scanner.ref_dist reflectivity_limit = scanner.ref_limit reflectivity_slope = scanner.ref_slope origin = Vector([0.0,0.0,0.0]) direction = Vector([0.0,0.0,0.0]) hit_indices = [-1]*numberOfRays for idx in range(numberOfRays): direction.x = rays_buffer[idx*elementsPerRay] direction.y = rays_buffer[idx*elementsPerRay+1] direction.z = rays_buffer[idx*elementsPerRay+2] if elementsPerRay>=6: origin.x = rays_buffer[idx*elementsPerRay+3] origin.y = rays_buffer[idx*elementsPerRay+4] origin.z = rays_buffer[idx*elementsPerRay+5] else: origin.x = bpy.context.scene.camera.location.x origin.y = bpy.context.scene.camera.location.y origin.z = bpy.context.scene.camera.location.z direction.rotate (scanner.matrix_world) (hit_loc, hit_normal, hit_idx, hit_distance) = scene_bvh.ray_cast(origin,direction,max_distance) valid_return = False if hit_loc: mat = mat_array[hit_idx] diffuse_intensity = 1.0 if mat: diffuse_intensity = mat.diffuse_intensity #Calculate the required diffuse reflectivity of the material to create a return ref_limit = blensor_calculate_reflectivity_limit(hit_distance, reflectivity_distance, reflectivity_limit, reflectivity_slope) if diffuse_intensity > ref_limit: valid_return = True if mat: color = mat.diffuse_color returns_buffer[idx*ELEMENTS_PER_RETURN+5] = color.r returns_buffer[idx*ELEMENTS_PER_RETURN+6] = color.g returns_buffer[idx*ELEMENTS_PER_RETURN+7] = color.b else: returns_buffer[idx*ELEMENTS_PER_RETURN+5] = 1.0 returns_buffer[idx*ELEMENTS_PER_RETURN+6] = 1.0 returns_buffer[idx*ELEMENTS_PER_RETURN+7] = 1.0 returns_buffer[idx*ELEMENTS_PER_RETURN] = hit_distance returns_buffer[idx*ELEMENTS_PER_RETURN+1] = hit_loc.x returns_buffer[idx*ELEMENTS_PER_RETURN+2] = hit_loc.y returns_buffer[idx*ELEMENTS_PER_RETURN+3] = hit_loc.z obj = obj_array[hit_idx] name = obj.name returns_buffer[idx*ELEMENTS_PER_RETURN+4] = ord(name[0]) + (ord(name[1])<<8) + (ord(name[2])<<16) + (ord(name[3])<<24) hit_indices[idx] = hit_idx if not valid_return: for r in range(ELEMENTS_PER_RETURN): returns_buffer[idx*ELEMENTS_PER_RETURN+r] = 0.0 # Step 3: Shade rays # TODO: Implement material solver if do_shading: for idx,mat_idx in enumerate(hit_indices): if mat_idx >= 0: #shade hit point pass
def from_object(model, obj, root): node = Mesh(name=obj.name) triangulated_object, created_temp_mesh = create_triangulated_mesh(obj) # apply rotation and scale transform to the object # this ensures that any modifications are baked to the vertices # before we output them to the file triangulated_object.select = True # This is used to transform the vertices and normals of the mesh. world_matrix = model.global_matrix * triangulated_object.matrix_world.copy() mesh = triangulated_object.to_mesh(bpy.context.scene, True, 'PREVIEW') # collect all blender materials used by this mesh for bmaterial in mesh.materials: mat = model.add_material(bmaterial) node.material_id = mat.index cache = VertexCache() bone_data = Mesh.process_armature(model, node, cache, obj) model.bone_data = bone_data weights = [[None]] * len(mesh.vertices) vertices = [] mins = Vector((9999, 9999, 9999)) maxs = Vector((-9999, -9999, -9999)) # build a mapping from group index to bone index total_bones = len(bone_data.ordered_items) if bone_data else 0 group_index_to_bone = [None] * total_bones for group in obj.vertex_groups: # convert group index to boneinfo.index boneinfo = bone_data.find_by_name(group.name) if not boneinfo: # It's possible to have vertex groups for bones which # may have been removed. Ignore these. continue group_index_to_bone[group.index] = boneinfo for index, mv in enumerate(mesh.vertices): position = world_matrix * mv.co vertices.extend([( position[0], position[1], position[2])]) if position[0] < mins.x: mins.x = position[0] elif position[0] > maxs.x: maxs.x = position[0] if position[1] < mins.y: mins.y = position[1] elif position[1] > maxs.y: maxs.y = position[1] if position[2] < mins.z: mins.z = position[2] elif position[2] > maxs.z: maxs.z = position[2] # don't add out of range indices weights[index] = [] for group_element in mv.groups: if group_element.group < total_bones: bone = group_index_to_bone[group_element.group] if bone and group_element.weight > 0.0: if len(weights[index]) < 4: weights[index].append({ "bone": bone.name, "value": group_element.weight }) #else: # print("warning: dropping weight for bone '%s', %2.2f" % (bone.name, group_element.weight)) node.mins = [mins.x, mins.y, mins.z] node.maxs = [maxs.x, maxs.y, maxs.z] mesh.calc_normals_split() normals = [] for loop in mesh.loops: # transform normals normal = (world_matrix.to_3x3() * loop.normal).normalized() normals.append((normal[0], normal[1], normal[2])) mesh.free_normals_split() uvs = [] if not mesh.uv_layers: uv_set = [(0.0, 0.0)] * len(mesh.loops) uvs.append(uv_set) else: for uvlayer in mesh.uv_layers: uv_set = [] print("extracting uv layer: %s" % uvlayer.name) for uvloop in uvlayer.data: uv_set.append([uvloop.uv[0], 1.0-uvloop.uv[1]]) uvs.append(uv_set) colors = [] if not mesh.vertex_colors: # add a default color set color_set = ([(1.0, 1.0, 1.0, 1.0)] * len(mesh.loops)) colors.append(color_set) else: for color_layer in mesh.vertex_colors: color_set = [] print("extracting color layer: %s" % color_layer.name) for data in color_layer.data: color_set.append((data.color[0], data.color[1], data.color[2], 1.0)) colors.append(color_set) if weights: print("total weights: %i, total vertices: %i" % (len(weights), len(vertices))) assert(len(weights) == len(vertices)) # convert and copy geometry over to node cache.populate_with_geometry(vertices, normals, uvs, colors, mesh.loops, weights=weights) node.populate_with_vertex_cache(cache) # de-select the previously selected object triangulated_object.select = False if created_temp_mesh: # remove the triangulated object we created bpy.ops.object.mode_set(mode='OBJECT') bpy.context.scene.objects.unlink(triangulated_object) return node
def write_mesh(context, filepath, use_apply_modifiers, float_precision, include_normals, include_tangents, include_bitangents, include_uvs, include_colors, include_weights, bones_per_vertex, global_matrix, export_skeleton, export_materials, copy_images): # Allocate mesh data vertices = [] vertex_set = set() triangles = [] submeshes = [] bounds_min = Vector((float("inf"), float("inf"), float("inf"))) bounds_max = Vector((-float("inf"), -float("inf"), -float("inf"))) armature = None # Determine vertex format vertex_format = "position" if include_uvs: vertex_format += " uv" if include_normals: vertex_format += " normal" if include_tangents: vertex_format += " tangent" if include_bitangents: vertex_format += " bitangent" if include_colors: vertex_format += " color" if include_weights: vertex_format += " indices%d weights%d" % (bones_per_vertex, bones_per_vertex) # Select objects to export object = context.object try: mesh = object.to_mesh(context.scene, use_apply_modifiers, "PREVIEW") except: return armature = object.parent bm = bmesh.new() bm.from_mesh(mesh) bm.transform(global_matrix * object.matrix_world) bmesh.ops.triangulate(bm, faces=bm.faces) bm.normal_update() uv_layer = bm.loops.layers.uv.active color_layer = bm.loops.layers.color.active deform_layer = bm.verts.layers.deform.active # Sort faces by material faces = bm.faces[:] faces.sort(key=lambda a: a.material_index) # Create empty submesh submesh = Submesh() previous_material_index = -1 for face in faces: triangle_indices = [] # Change material if face.material_index != previous_material_index: # Update primitive count of previous submesh submesh.primitive_count = len(triangles) - (submesh.start_index / 3) # Create a new submesh submesh = Submesh() submesh.material = object.material_slots[face.material_index].material submesh.start_index = len(triangles) * 3 submeshes.append(submesh) previous_material_index = face.material_index for loop in face.loops: vert = loop.vert v = Vertex() v.position = vert.co.copy() if include_normals: if face.smooth: v.normal = vert.normal.copy() else: v.normal = face.normal.copy() if include_uvs and uv_layer is not None: v.uv = loop[uv_layer].uv.copy() if include_colors and color_layer is not None: v.color = loop[color_layer].color.copy() if include_tangents or include_bitangents: tangent_space = calculate_tangent_space(vert, uv_layer) v.tangent = tangent_space[0] v.bitangent = tangent_space[1] if include_weights and deform_layer is not None: # Sort bones by most influential sorted_groups = sorted(vert[deform_layer].items(), key=lambda item: item[1], reverse=True) # Set vertex bone weights and calculate sum weight_total = 0.0 for i in range(min(bones_per_vertex, len(sorted_groups))): vertex_group = object.vertex_groups[sorted_groups[i][0]] bone_index = armature.data.bones.find(vertex_group.name) v.indices[i] = bone_index v.weights[i] = sorted_groups[i][1] weight_total += v.weights[i] # Normalize weights if weight_total > 0.0: v.weights *= 1.0 / weight_total if v not in vertex_set: vertex_set.add(v) triangle_indices.append(len(vertices)) vertices.append(v) # Update bounds bounds_min.x = min(bounds_min.x, v.position.x) bounds_min.y = min(bounds_min.y, v.position.y) bounds_min.z = min(bounds_min.z, v.position.z) bounds_max.x = max(bounds_max.x, v.position.x) bounds_max.y = max(bounds_max.y, v.position.y) bounds_max.z = max(bounds_max.z, v.position.z) else: triangle_indices.append(vertices.index(v)) triangles.append(triangle_indices) # Free BMesh bm.free() # Finalize last submesh submesh.primitive_count = len(triangles) - (submesh.start_index / 3) root_node = AttributeTreeNode() root_node.set_attribute("version", OGF_VERSION_STRING) mesh_node = root_node.create_child() mesh_node.set_attribute("type", "mesh") mesh_node.set_attribute("name", os.path.splitext(os.path.basename(filepath))[0]) mesh_node.set_attribute("vertex_format", vertex_format) mesh_node.set_attribute("vertex_count", str(len(vertices))) # Write vertices vertices_attrib = "" for v in vertices: vertices_attrib += float3_format.format(float_precision, *v.position) + ' ' if include_uvs: vertices_attrib += float2_format.format(float_precision, *v.uv) + ' ' if include_normals: vertices_attrib += float3_format.format(float_precision, *v.normal) + ' ' if include_tangents: vertices_attrib += float3_format.format(float_precision, *v.tangent.xyz) + ' ' if include_bitangents: vertices_attrib += float3_format.format(float_precision, *v.bitangent.xyz) + ' ' if include_colors: vertices_attrib += float3_format.format(float_precision, *v.color) + ' ' if include_weights: for i in range(bones_per_vertex): vertices_attrib += "{} ".format(v.indices[i]) for i in range(bones_per_vertex): vertices_attrib += float_format.format(float_precision, v.weights[i]) + ' ' mesh_node.set_attribute("vertices", vertices_attrib) mesh_node.set_attribute("index_count", str(len(triangles) * 3)) # Write indices indices_attrib = "" for t in triangles: indices_attrib += "{} {} {} ".format(*t) mesh_node.set_attribute("indices", indices_attrib) # Write bounds mesh_node.set_attribute("bounds_min", float3_format.format(float_precision, *bounds_min)) mesh_node.set_attribute("bounds_max", float3_format.format(float_precision, *bounds_max)) # Export skeleton if export_skeleton and object.parent is not None and object.parent.type == "ARMATURE": write_skeleton(filepath, float_precision, global_matrix, object.parent) mesh_node.set_attribute("skeleton", object.parent.name + ".skeleton") for submesh in submeshes: material_filename = submesh.material.name + ".material" submesh_node = mesh_node.create_child() submesh_node.set_attribute("type", "submesh") submesh_node.set_attribute("material", material_filename) submesh_node.set_attribute("primitive_type", "triangle_list") submesh_node.set_attribute("start_index", str(submesh.start_index)) submesh_node.set_attribute("primitive_count", str(int(submesh.primitive_count))) file = open(filepath, "w", encoding="utf8", newline='\n') root_node.serialize(file) file.close() # Export materials if export_materials: for submesh in submeshes: write_material(filepath, copy_images, float_precision, submesh.material)
def make_tetras(cls, vertices): ## 1 : 点群を包含する四面体を求める ## 1-1: 点群を包含する球を求める v_max = Vector((-999, -999, -999)) v_min = Vector(( 999, 999, 999)) for v in vertices: if v_max.x < v.x: v_max.x = v.x if v_max.y < v.y: v_max.y = v.y if v_max.z < v.z: v_max.z = v.z if v_min.x > v.x: v_min.x = v.x if v_min.y > v.y: v_min.y = v.y if v_min.z > v.z: v_min.z = v.z center = (v_max - v_min)*0.5 r = max([(center-v).length for v in vertices]) ## 半径 r += 0.1 ## ちょっとおまけ ## 1-2: 球に外接する四面体を求める v1 = Vector(( center.x , center.y + 3.0*r , center.z )) v2 = Vector(( center.x - 2.0*math.sqrt(2)*r , center.y - r , center.z )) v3 = Vector(( center.x + math.sqrt(2)*r , center.y - r , center.z + math.sqrt(6)*r )) v4 = Vector(( center.x + math.sqrt(2)*r , center.y - r , center.z - math.sqrt(6)*r )) outer = [v1, v2, v3, v4] tetras = [] tetras.append(Tetrahedron(v1, v2, v3, v4)) def to_identifier(tetra): vs = sorted(tetra.vertices, key=lambda v:v.x) a,b,c,d = vs return '{}/{}/{}//{}/{}/{}//{}/{}/{}//{}/{}/{}'.format( a.x,a.y,a.z , b.x,b.y,b.z , c.x,c.y,c.z , d.x,d.y,d.z ) def __scan__(hash_tetras, hash_added, tetra): ide = to_identifier(tetra) if ide in hash_added: if ide in hash_tetras: del hash_tetras[ide] return hash_tetras[ide] = tetra hash_added[ide] = True ## 幾何形状を動的に変化させるための一時リスト for v in vertices: hash_tetras = {} hash_added = {} tmp_tlist = [] for t in tetras: if t.o is not None and t.r > (v - t.o).length: tmp_tlist.append(t) for t1 in tmp_tlist: ## まずそれらを削除 tetras.remove(t1) v1 = t1.vertices[0] v2 = t1.vertices[1] v3 = t1.vertices[2] v4 = t1.vertices[3] __scan__(hash_tetras, hash_added, Tetrahedron(v1, v2, v3, v)) __scan__(hash_tetras, hash_added, Tetrahedron(v1, v2, v4, v)) __scan__(hash_tetras, hash_added, Tetrahedron(v1, v3, v4, v)) __scan__(hash_tetras, hash_added, Tetrahedron(v2, v3, v4, v)) for t in hash_tetras.values(): tetras.append( t ) def cleanup(tetras, t4): for p1 in t4.vertices: for p2 in outer: #if p1.x == p2.x and p1.y == p2.y and p1.z == p2.z: if p1 == p2: tetras.remove(t4) return for t4 in tetras.copy(): cleanup(tetras, t4) return tetras
def execute(self, context): if self.sculpties == []: return {'CANCELLED'} sculpt_bb = {} gmin = None gmax = None edit_mode = context.mode == 'EDIT_MESH' if edit_mode: bpy.ops.object.editmode_toggle() if self.reset_origin: for obj in self.sculpties + self.objects: if 'MIRROR' not in [m.type for m in obj.modifiers]: bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN') for obj in self.sculpties: mesh = obj.to_mesh(context.scene, True, 'RENDER') vmin, vmax = bounding_box(mesh) if not self.reset_origin: vmax.x = max(abs(vmin.x), abs(vmax.x)) vmin.x = -vmax.x vmax.y = max(abs(vmin.y), abs(vmax.y)) vmin.y = -vmax.y vmax.z = max(abs(vmin.z), abs(vmax.z)) vmin.z = -vmax.z if self.aligned: if gmin is None: gmin = Vector((vmin.x, vmin.y, vmin.z)) gmax = Vector((vmax.x, vmax.y, vmax.z)) else: gmin.x = min(gmin.x, vmin.x) gmin.y = min(gmin.y, vmin.y) gmin.z = min(gmin.z, vmin.z) gmax.x = max(gmax.x, vmax.x) gmax.y = max(gmax.y, vmax.y) gmax.z = max(gmax.z, vmax.z) sculpt_bb[obj.name] = (vmin, vmax) if self.use_objects: for obj in self.objects: mesh = obj.to_mesh(context.scene, True, 'RENDER') vmin, vmax = bounding_box(mesh) if gmin is None: gmin = Vector((vmin.x, vmin.y, vmin.z)) gmax = Vector((vmax.x, vmax.y, vmax.z)) else: gmin.x = min(gmin.x, vmin.x) gmin.y = min(gmin.y, vmin.y) gmin.z = min(gmin.z, vmin.z) gmax.x = max(gmax.x, vmax.x) gmax.y = max(gmax.y, vmax.y) gmax.z = max(gmax.z, vmax.z) if not self.reset_origin: gmax.x = max(abs(gmin.x), abs(gmax.x)) gmin.x = -gmax.x gmax.y = max(abs(gmin.y), abs(gmax.y)) gmin.y = -gmax.y gmax.z = max(abs(gmin.z), abs(gmax.z)) gmin.z = -gmax.z for obj_name in sculpt_bb: smin, smax = sculpt_bb[obj_name] if gmin is not None: if self.aligned: vmin = Vector((gmin.x, gmin.y, gmin.z)) vmax = Vector((gmax.x, gmax.y, gmax.z)) else: vmin.x = min(gmin.x, smin.x) vmin.y = min(gmin.y, smin.y) vmin.z = min(gmin.z, smin.z) vmax.x = max(gmax.x, smax.x) vmax.y = max(gmax.y, smax.y) vmax.z = max(gmax.z, smax.z) if self.optimise: # try to improve bake range. Make sure that # any increases don't go beyond the original mesh f = floor((vmax.x - vmin.x) / (smax.x - smin.x)) if f > 1.0: size = (vmax.x - vmin.x) * 0.5 center = vmin.x + size vmin.x = center - size / f vmax.x = center + size / f f = floor((vmax.y - vmin.y) / (smax.y - smin.y)) if f > 1.0: size = (vmax.y - vmin.y) * 0.5 center = vmin.y + size vmin.y = center - size / f vmax.y = center + size / f f = floor((vmax.z - vmin.z) / (smax.z - smin.z)) if f > 1.0: size = (vmax.z - vmin.z) * 0.5 center = vmin.z + size vmin.z = center - size / f vmax.z = center + size / f else: vmin = smin vmax = smax if self.red_scale != 100.0: red_range = vmax.x - vmin.x if self.red_scale == 0.0: red_adjust = red_range / 2.0 else: new_range = red_range * 100.0 / self.red_scale red_adjust = (new_range - red_range) / 2.0 vmin.x -= red_adjust vmax.x += red_adjust if self.green_scale != 100.0: green_range = vmax.y - vmin.y if self.green_scale == 0.0: green_adjust = green_range / 2.0 else: new_range = green_range * 100.0 / self.green_scale green_adjust = (new_range - green_range) / 2.0 vmin.y -= green_adjust vmax.y += green_adjust if self.blue_scale != 100.0: blue_range = vmax.z - vmin.z if self.blue_scale == 0.0: blue_adjust = blue_range / 2.0 else: new_range = blue_range * 100.0 / self.blue_scale blue_adjust = (new_range - blue_range) / 2.0 vmin.z -= blue_adjust vmax.z += blue_adjust bake(bpy.data.objects[obj_name], context.scene, vmin, vmax, self.update_name) for a in context.window.screen.areas: for s in a.spaces: if s.type == 'IMAGE_EDITOR': # force refresh for missing images set to generated if s.image is not None: t = bpy.data.images[s.image.name] s.image = t if a.type == 'IMAGE_EDITOR': a.tag_redraw() if edit_mode: bpy.ops.object.editmode_toggle() if not self.no_dialog: context.scene['sculpty_bake'] = { 'r': self.red_scale, 'g': self.green_scale, 'b': self.blue_scale, 'ro': self.reset_origin, 'uo': self.use_objects, 'a': self.aligned, 'o': self.optimise} return {'FINISHED'}
def main(self, context): obj = context.active_object me = obj.data bm = bmesh.from_edit_mesh(me) face_sets = [] faces = [] force_orthogonal = self.properties.force_orthogonal method = self.properties.method # store data for f in bm.faces: if f.select: if method == 'AVERAGE': faces.append (f) elif method == 'INDIVIDUAL': face_sets.append ([f]) if method == 'AVERAGE': face_sets.append (faces) for fs in face_sets: normal = Vector () center = Vector () for f in fs: normal += f.normal center += f.calc_center_median_weighted () normal.normalize () center /= len (fs) if force_orthogonal: x = abs (normal.x) y = abs (normal.y) z = abs (normal.z) if x > y and x > z: normal.x /= x normal.y = 0.0 normal.z = 0.0 if y > x and y > z: normal.x = 0.0 normal.y /= y normal.z = 0.0 if z > y and z > x: normal.x = 0.0 normal.y = 0.0 normal.z /= z for f in fs: for v in f.verts: d = geometry.distance_point_to_plane (v.co, center, normal) v.co -= normal * d bmesh.update_edit_mesh(me)
def recursive_aabb(facelist, parent, level): """ Recursively build a tree of aabb nodes, returns the root of the subtree. """ # This code is heavily inspired by nwmax and Waylands original code if level > 20: raise RuntimeError("Max recursion depth reached when building aabb " "tree. Look for duplicate faces.") bottom_left = Vector((10000, 10000, 10000)) top_right = Vector((-10000, -10000, -10000)) midpoints = Vector((0, 0, 0)) # First we calculate the bounding box for face in facelist: for x, y, z in face["verts"]: if x < bottom_left.x: bottom_left.x = x if y < bottom_left.y: bottom_left.y = y if z < bottom_left.z: bottom_left.z = z if x > top_right.x: top_right.x = x if y > top_right.y: top_right.y = y if z > top_right.z: top_right.z = z midpoints += face["center"] midpoint = midpoints / len(facelist) bounding_box = {"co1": bottom_left[:], "co2": top_right[:], "index": -1, "left": None, "right": None, "parent": parent} ## If this is a leaf we're done if len(facelist) == 1: bounding_box["index"] = facelist[0]["index"] return bounding_box ## Otherwise we have to decide how to do the splits splits = {"x": {"left": [], "right": []}, "y": {"left": [], "right": []}, "z": {"left": [], "right": []}} #find the best split, which is the split where the two sides are balanced for face in facelist: if face["center"].x < midpoint.x: splits["x"]["left"].append(face) else: splits["x"]["right"].append(face) if face["center"].y < midpoint.y: splits["y"]["left"].append(face) else: splits["y"]["right"].append(face) if face["center"].z < midpoint.z: splits["z"]["left"].append(face) else: splits["z"]["right"].append(face) split = None #We calculate the difference between the two sides delta_x = abs(len(splits["x"]["right"]) - len(splits["x"]["left"])) delta_y = abs(len(splits["y"]["right"]) - len(splits["y"]["left"])) delta_z = abs(len(splits["z"]["right"]) - len(splits["z"]["left"])) # We pick the split where the difference between the splits are as small as possible if delta_x < delta_y and delta_x < delta_z: split = splits["x"] elif delta_y < delta_z: split = splits["y"] else: split = splits["z"] if split["left"]: bounding_box["left"] = recursive_aabb(split["left"], bounding_box, level + 1) if split["right"]: bounding_box["right"] = recursive_aabb(split["right"], bounding_box, level + 1) return bounding_box
def main(filename): sce = bpy.context.scene obs = sce.objects dfaces = {} f = open(filename, 'w') f.write('<?xml version="1.0" encoding="utf-8"?>\n<scene>\n\t<directionalLight>\n\t\t<color r="255" g="255" b="255"/>\n\t\t<direction x="-1" y="-1" z="-1"/>\n\t</directionalLight>\n\t<ambientLight>\n\t\t<color r="255" g="255" b="255"/>\n\t</ambientLight>\n') for ob in obs: if ob.type == 'CAMERA': camz = Vector().to_4d() camy = Vector().to_4d() camy.y = 1 camy.w = 0 camz.z = -10 #camz.w = 0 target = ob.matrix_world * camz normal = ob.matrix_world*camy f.write('\t<camera>\n') f.write('\t\t<position x="%f" y="%f" z="%f"/>\n' %(ob.location.x, ob.location.y, ob.location.z)) f.write('\t\t<target x="%f" y="%f" z="%f"/>\n' %(target.x, target.y, target.z)) f.write('\t\t<normal x="%f" y="%f" z="%f"/>' % (normal.x, normal.y, normal.z)) f.write('\n\t\t<viewplane w="16/2" h="9/2" d="%f"/>\n\t</camera>\n' %(ob.data.lens/4)) if ob.type == 'MESH': dfaces = {} mesh = ob.data verts = mesh.vertices ob_mat = ob.matrix_world scale = Matrix() scale[0][0] = ob.scale.x scale[1][1] = ob.scale.y scale[2][2] = ob.scale.z verts = [ob_mat * scale * vert.co.to_4d() for vert in verts] faces = mesh.polygons for face in faces: material = Material() if len(ob.material_slots) > 0: #print("index", face.material_index) mat = ob.material_slots[face.material_index].material if mat.use_vertex_color_paint: material.color = mesh.vertex_colors[0].data[face.index].color1 else: material.color = mat.diffuse_color if mat.use_transparency: material.transparency= mat.raytrace_transparency.fresnel_factor if mat.use_raytrace: material.reflexivity = mat.raytrace_mirror.reflect_factor material.ambiant = mat.ambient material.diffuse = mat.diffuse_intensity material.specular = mat.specular_intensity material.shininess = mat.specular_hardness if not material in dfaces: dfaces[material] = [] dfaces[material].append(face) for material in dfaces: f.write("\t<object>\n") f.write('\t\t<shape>\n') f.write('\t\t\t<list>\n') for face in dfaces[material]: vs = face.vertices if len(vs)==3: writeTriangle(f, mesh.vertices, verts, vs, material) elif len(vs)==4: vs1 = vs[:3] vs2 = [vs[0],vs[2], vs[3]] writeTriangle(f, mesh.vertices, verts, vs1, material) writeTriangle(f, mesh.vertices, verts, vs2, material) else: print("Pas de face") f.write('\t\t\t</list>\n') f.write('\t\t</shape>\n') f.write('\t\t<material>\n\t\t\t<phong>\n') f.write('\t\t\t\t<color r="%d" g="%d" b="%d"/>\n' % (int(255*material.color.r), int(255*material.color.g), int(255*material.color.b))) f.write('\t\t\t\t<specular v="%f"/>\n' % (material.specular)) f.write('\t\t\t\t<diffuse v="%f"/>\n' % (material.diffuse)) f.write('\t\t\t\t<ambiant v="%f"/>\n' % (material.ambiant)) f.write('\t\t\t\t<shininess v="%f"/>\n' % (material.shininess)) f.write('\t\t\t\t<reflexivity v="%f"/>\n' % (material.reflexivity)) f.write('\t\t\t\t<transparency v="%f"/>\n' % (material.transparency)) f.write('\t\t\t</phong>\n\t\t</material>\n') f.write("\t</object>\n") f.write("</scene>") f.close() print ("\nExport to PRay xml completed.") return {'FINISHED'}