def rand_rot(v, mean_branch_angle): v_temp = Vector((v.x, v.z, v.y)) cross1 = v.cross(v_temp) cross2 = v.cross(cross1) branch_angle = random.gauss(mean_branch_angle, branch_sigma) q1 = Quaternion(cross1, radians(branch_angle)) q2 = Quaternion(q1) angle = random.uniform(0.0, math.pi) q1.rotate(Quaternion(v, angle)) q2.rotate(Quaternion(v, angle + math.pi)) return q1.to_euler(), q2.to_euler()
def rotateCam(rift): cont = G.getCurrentController() owner = cont.owner scene = G.getCurrentScene() rift.poll() rotation = Quaternion((rift.rotation[0], rift.rotation[1], rift.rotation[2], rift.rotation[3])) eu = rotation.to_euler() #ativecam fix = Euler((-1.57, 0, 3 * 1.57), 'XYZ') rot = Euler((-eu.z, eu.y, -eu.x), 'XYZ') #owner #fix = Euler((0, 2*-1.57, -1.57), 'XYZ') #rot = Euler((-eu.x, eu.z, eu.y), 'XYZ') rot.rotate(fix) #cam = scene.active_camera cam = scene.cameras["Camera"] cam.localOrientation = rot
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 set_body_position_orientation(): """ Le point '18' est au centre de [8, 11] soit au centre du bassin. Il ne vient pas de COCO ! Le bone spine suit les rotation de 18 sur Z """ # Position 8 à droite 11 à gauche if gl.points[8] and gl.points[11]: x = (gl.spheres[8].worldPosition[0] + gl.spheres[11].worldPosition[0]) / 2 y = (gl.spheres[8].worldPosition[1] + gl.spheres[11].worldPosition[1]) / 2 z = (gl.spheres[8].worldPosition[2] + gl.spheres[11].worldPosition[2]) / 2 gl.spheres[18].worldPosition = [x, y, z] gl.spheres[18].worldScale = [ 1.5 * gl.scale, 1.5 * gl.scale, 1.5 * gl.scale ] # Rotation: direction = de 11 à 8 if gl.points[8] and gl.points[11]: try: a = gl.spheres[8].worldPosition b = gl.spheres[11].worldPosition direction = (b - a).normalized() axis_align = Vector((1.0, 0.0, 0.0)) angle = axis_align.angle(direction) axis = axis_align.cross(direction) quat = Quaternion(axis, angle) gl.spheres[18].localOrientation = quat.to_euler('XYZ') except: pass
def apply_objet_position_orientation(objet_point_1, objet_point_2, objet): """Valable pour un objet seulement. objet_point_1, objet_point_2 sont 2 objets Blender: ils définissent un vecteur. L'objet objet est orienté suivant ce vecteur, si objet_point_2 n'est pas None et positionné en objet_point_1. """ if objet_point_2: try: a = objet_point_1.worldPosition b = objet_point_2.worldPosition direction = (b - a).normalized() axis_align = Vector((1.0, 0.0, 0.0)) angle = axis_align.angle(direction) axis = axis_align.cross(direction) quat = Quaternion(axis, angle) objet.localOrientation = quat.to_euler('XYZ') sc = (b - a).length # Les coefficients correspondent à la taille des objects cube # qui représentent les os objet.localScale = [ sc * 5 * gl.scale, 0.2 * gl.scale, 0.2 * gl.scale ] except: pass # Apply position objet.worldPosition = objet_point_1.worldPosition
def get_align_target_vector(self, context: bpy.types.Context): if self.align_target == 'camera': return context.scene.camera.rotation_euler elif self.align_target == 'view': return Quaternion.to_euler(context.region_data.view_rotation) else: raise ValueError('Invalid align target!')
def get_matrix_world_at_frame(obj, frame_id): rotation_mode = get_rotation_mode_at_frame(obj, frame_id) if rotation_mode == 'AXIS_ANGLE': axis_angle = get_vector4_at_frame(obj, "rotation_axis_angle", frame_id) angle = axis_angle[0] axis = Vector((axis_angle[1], axis_angle[2], axis_angle[3])) rotation_matrix = Matrix.Rotation(angle, 4, axis) elif rotation_mode == 'QUATERNION': rotation_quat = get_vector4_at_frame(obj, "rotation_quaternion", frame_id) quaternion = Quaternion(rotation_quat) rotation_matrix = quaternion.to_euler().to_matrix().to_4x4() else: rotation = get_vector3_at_frame(obj, "rotation_euler", frame_id) euler_rotation = Euler(rotation, rotation_mode) rotation_matrix = euler_rotation.to_matrix().to_4x4() location = get_vector3_at_frame(obj, "location", frame_id) location_matrix = Matrix.Translation(location).to_4x4() scale = get_vector3_at_frame(obj, "scale", frame_id) scale_matrix = Matrix.Identity(4) scale_matrix[0][0] = scale[0] scale_matrix[1][1] = scale[1] scale_matrix[2][2] = scale[2] return vcu.element_multiply( vcu.element_multiply(location_matrix, rotation_matrix), scale_matrix)
def rotateCam(rift): cont = G.getCurrentController() owner = cont.owner scene = G.getCurrentScene() rift.poll() rotation = Quaternion((rift.rotation[0], rift.rotation[1], rift.rotation[2], rift.rotation[3])) eu = rotation.to_euler() #ativecam fix = Euler((-1.57, 0, 3*1.57), 'XYZ') rot = Euler((-eu.z, eu.y, -eu.x), 'XYZ') #owner #fix = Euler((0, 2*-1.57, -1.57), 'XYZ') #rot = Euler((-eu.x, eu.z, eu.y), 'XYZ') rot.rotate(fix) #cam = scene.active_camera cam = scene.cameras["Camera"] cam.localOrientation = rot
def setObjectRotationQuaternion(obj: bpy.types.Object, rot: Quaternion): if obj.rotation_mode == "QUATERNION": obj.rotation_quaternion = rot elif obj.rotation_mode == "AXIS_ANGLE": obj.rotation_axis_angle = rot.to_axis_angle() else: obj.rotation_euler = rot.to_euler(obj.rotation_mode)
def _apply_transforms(container: Source1ModelContainer, animset: AnimationSet, scale=HAMMER_UNIT_TO_METERS): for control in animset.controls: if control.type == 'DmElement': pass # flex elif control.type == 'DmeTransformControl': bone_name = control.name tmp = control['valuePosition'] pos = Vector(tmp) * scale rot = _convert_quat(control['valueOrientation']) if container.armature: arm = container.armature bone = arm.pose.bones.get(bone_name, None) if bone: qrot = Quaternion() qrot.x, qrot.y, qrot.z, qrot.w = rot # rot.x,rot.y,rot.z,rot.w = bone_.valueOrientation erot = qrot.to_euler('YXZ') if not bone.parent: pos = arm.data.bones.get(bone_name).head - pos # new_rot = Euler([math.pi / 2, 0, 0]).rotate(erot) mat = Matrix.Translation(pos) @ erot.to_matrix().to_4x4() bone.matrix_basis.identity() bone.matrix = bone.parent.matrix @ mat if bone.parent else mat
def get_direction_of_verts(a, b): direction = (a - b).normalized() axis_align = Vector((0.0, 0.0, 1.0)) angle = axis_align.angle(direction) axis = axis_align.cross(direction) q = Quaternion(axis, angle) return q.to_euler('XYZ')
def getOculusOri(self): self.pyrift.poll() oculus_ori = Quaternion( (self.pyrift.rotation[0], self.pyrift.rotation[1], self.pyrift.rotation[2], self.pyrift.rotation[3])) eu = oculus_ori.to_euler() eu = oculus_ori.to_euler() fix = Euler((-math.pi / 2, 0., math.pi / 2), 'XYZ') ori = Euler((-eu.z, eu.y, -eu.x), 'XYZ') ori.rotate(fix) return ori
def VSLAMTestMappingBlenderDSO(): # Test Mapping: translation = Vector([-1, 21, 22]) quaternion = Quaternion((1.0, 0.0, 0.0, 0.0)) print("Blender (original): \t", translation, " - ", quaternion.to_euler('XYZ')) dso_trans, dso_rot = VSLAMMappingFromBlender2DSO(translation, quaternion) print("DSO: \t\t\t", dso_trans, " - ", dso_rot) blender_trans, blender_rot = VSLAMMappingFromDSO2Blender( dso_trans, dso_rot) print("Blender (retrieved): \t", blender_trans, " - ", blender_rot.to_euler('XYZ')) if translation == blender_trans and quaternion == blender_rot: print("Everything O.K.!") else: print("Mapping test failed... ... -.-")
def set_bound_transform(bounds, obj): locationn = bounds.find("CompositePosition") location = Vector( (float(locationn.attrib["x"]), float(locationn.attrib["y"]), float(locationn.attrib["z"]))) obj.location = location rotationn = bounds.find("CompositeRotation") rotation = Quaternion( (float(rotationn.attrib["w"]), float(rotationn.attrib["x"]), float(rotationn.attrib["y"]), float(rotationn.attrib["z"]))) obj.rotation_euler = rotation.to_euler() scalen = bounds.find("CompositeScale") scale = Vector((float(scalen.attrib["x"]), float(scalen.attrib["y"]), float(scalen.attrib["z"]))) obj.scale = scale return obj
def _arc_segment(v_1, v_2): ELorigin = bpy.context.scene.objects['ELorigin'] ELground = bpy.context.scene.objects['ELground'] v = v_2 - v_1 d = v.length ELorigin.location = Vector((0, 0, 0)) ELground.location = Vector((0, 0, -d)) v_L = ELground.location - ELorigin.location q = Quaternion() c = Vector.cross(v_L, v) q.x = c.x q.y = c.y q.z = c.z q.w = sqrt((v_L.length ** 2) * (v.length ** 2)) + \ Vector.dot(v_L, v) q.normalize() euler = q.to_euler() bpy.ops.object.runfslg_operator() laALL = bpy.context.scene.objects['laALL'] laALL.name = 'lARC' laALL.rotation_euler = euler laALL.location = v_1 bpy.context.active_object.select = False laALL.select = True bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) laALL.select = False bpy.context.active_object.select = True return laALL
def determineRootBoneRotation(self, bonesAnim): # direction based on https://social.msdn.microsoft.com/Forums/en-US/8f405acb-7758-4f5c-a297-24bdce27d042/understanding-subject-orientation?forum=kinectv2sdk sLeft = bonesAnim[SHOULDER_LEFT]['location'] sRight = bonesAnim[SHOULDER_RIGHT]['location'] sideToSide = Vector( (sLeft['x'] - sRight['x'], sLeft['z'] - sRight['z'], sLeft['y'] - sRight['y'])).normalized() print('sideToSide x: ' + ('%.2f' % sideToSide.x) + ', y: ' + ('%.2f' % sideToSide.y) + ', z: ' + str('%.2f' % sideToSide.z)) root = bonesAnim[SPINE_BASE]['location'] head = bonesAnim[HEAD]['location'] up = Vector((head['x'] - root['x'], head['z'] - root['z'], head['y'] - root['y'])).normalized() print('up ' + str(up.x) + ',' + str(up.y) + ',' + str(up.z)) print('up x: ' + ('%.2f' % up.x) + ', y: ' + ('%.2f' % up.y) + ', z: ' + str('%.2f' % up.z)) direction = sideToSide.cross(up) # from a direction to a rotation use https://gamedev.stackexchange.com/questions/118960/convert-a-direction-vector-normalized-to-rotation angle = atan2(direction.y, direction.x) rotXY = Quaternion((0.0, 0.0, 1.0), angle) #.to_matrix() euler = rotXY.to_euler() print( str(euler.x * 57.2958) + ', ' + str(euler.y * 57.2958) + ', ' + str(euler.z * 57.2958)) # 57.2958 is to degrees # angleZ = asin(direction.z) # rotZ = Quaternion((0.0, 1.0, 0.0), angleZ).to_matrix() # ret = (rotXY * rotZ).to_quaternion() # euler = ret.to_euler() # print(str(euler.x * 57.2958) + ', ' + str(euler.y * 57.2958) + ', ' + str(euler.z * 57.2958)) return rotXY
node.ui.add_button("calibrate_rotation", "Calibrate", "calibrate_rotation") node.ui.add_text("orientation") node.ui.add_text("temperature") node.ui.update() node.listen("calibrate_rotation", calibrate_rotation) if __name__ == "__main__": while node.running: for _ in range(30): x, y, z, w = bno.read_quaternion() raw = Quaternion([w, x, y, z]) corrected = raw.rotation_difference(calibration) node.broadcast( "orientation", [corrected.w, corrected.x, corrected.y, corrected.z]) time.sleep(1 / 30.0) e = corrected.to_euler() node.ui.get( "orientation")["text"] = "Orientation: %f %f %f" % (e.x, e.y, e.z) temperature = bno.read_temp() node.ui.get("temperature")["text"] = "Temperature: %f" % temperature node.broadcast("head_internal_temperature", temperature) node.ui.update()
def importWoWOBJ(objectFile, givenParent=None): baseDir, fileName = os.path.split(objectFile) print('Parsing OBJ: ' + fileName) ### OBJ wide material_libs = set() mtlfile = "" verts = [] normals = [] uv = [] meshes = [] ### Per group class OBJMesh: def __init__(self): self.usemtl = "" self.name = "" self.faces = [] curMesh = OBJMesh() meshIndex = -1 with open(objectFile, 'rb') as f: for line in f: line_split = line.split() if not line_split: continue line_start = line_split[0] if line_start == b'mtllib': mtlfile = line_split[1] elif line_start == b'v': verts.append([float(v) for v in line_split[1:]]) elif line_start == b'vn': normals.append([float(v) for v in line_split[1:]]) elif line_start == b'vt': uv.append([float(v) for v in line_split[1:]]) elif line_start == b'f': line_split = line_split[1:] meshes[meshIndex].faces.append( (int(line_split[0].split(b'/')[0]), int(line_split[1].split(b'/')[0]), int(line_split[2].split(b'/')[0]))) elif line_start == b'g': meshIndex += 1 meshes.append(OBJMesh()) meshes[meshIndex].name = line_split[1].decode("utf-8") elif line_start == b'usemtl': meshes[meshIndex].usemtl = line_split[1].decode("utf-8") ## Materials file (.mtl) materials = dict() matname = "" matfile = "" with open(os.path.join(baseDir, mtlfile.decode("utf-8")), 'r') as f: for line in f: line_split = line.split() if not line_split: continue line_start = line_split[0] if line_start == 'newmtl': matname = line_split[1] elif line_start == 'map_Kd': matfile = line_split[1] materials[matname] = os.path.join(baseDir, matfile) if bpy.ops.object.select_all.poll(): bpy.ops.object.select_all(action='DESELECT') # TODO: Better handling for dupes? objname = os.path.basename(objectFile) if objname in bpy.data.objects: objindex = 1 newname = objname while (newname in bpy.data.objects): newname = objname + '.' + str(objindex).rjust(3, '0') objindex += 1 newmesh = bpy.data.meshes.new(objname) obj = bpy.data.objects.new(objname, newmesh) ## Textures # TODO: Must be a better way to do this! materialmapping = dict() for matname, texturelocation in materials.items(): # Import material only once if (matname not in bpy.data.materials): mat = bpy.data.materials.new(name=matname) mat.use_nodes = True mat.blend_method = 'CLIP' principled = PrincipledBSDFWrapper(mat, is_readonly=False) principled.specular = 0.0 principled.base_color_texture.image = load_image(texturelocation) mat.node_tree.links.new( mat.node_tree.nodes['Image Texture'].outputs[1], mat.node_tree.nodes['Principled BSDF'].inputs[18]) obj.data.materials.append(bpy.data.materials[matname]) # TODO: Must be a better way to do this! materialmapping[matname] = len(obj.data.materials) - 1 ## Meshes bm = bmesh.new() i = 0 for v in verts: vert = bm.verts.new(v) vert.normal = normals[i] i = i + 1 bm.verts.ensure_lookup_table() bm.verts.index_update() for mesh in meshes: exampleFaceSet = False for face in mesh.faces: try: ## TODO: Must be a better way to do this, this is already much faster than doing material every face, but still. if exampleFaceSet == False: bm.faces.new((bm.verts[face[0] - 1], bm.verts[face[1] - 1], bm.verts[face[2] - 1])) bm.faces.ensure_lookup_table() bm.faces[-1].material_index = materialmapping[mesh.usemtl] bm.faces[-1].smooth = True exampleFace = bm.faces[-1] exampleFaceSet = True else: ## Use example face if set to speed up material copy! bm.faces.new((bm.verts[face[0] - 1], bm.verts[face[1] - 1], bm.verts[face[2] - 1]), exampleFace) except ValueError: ## TODO: Duplicate faces happen for some reason pass uv_layer = bm.loops.layers.uv.new() for face in bm.faces: for loop in face.loops: loop[uv_layer].uv = uv[loop.vert.index] bm.to_mesh(newmesh) bm.free() ## Rotate object the right way obj.rotation_euler = [0, 0, 0] obj.rotation_euler.x = radians(90) bpy.context.scene.collection.objects.link(obj) obj.select_set(True) ## WoW coordinate system max_size = 51200 / 3 map_size = max_size * 2 adt_size = map_size / 64 ## Import doodads and/or WMOs csvPath = objectFile.replace('.obj', '_ModelPlacementInformation.csv') if os.path.exists(csvPath): with open(csvPath) as csvFile: reader = csv.DictReader(csvFile, delimiter=';') if 'Type' in reader.fieldnames: importType = 'ADT' wmoparent = bpy.data.objects.new("WMOs", None) wmoparent.parent = obj wmoparent.name = "WMOs" wmoparent.rotation_euler = [0, 0, 0] wmoparent.rotation_euler.x = radians(-90) bpy.context.scene.collection.objects.link(wmoparent) doodadparent = bpy.data.objects.new("Doodads", None) doodadparent.parent = obj doodadparent.name = "Doodads" doodadparent.rotation_euler = [0, 0, 0] doodadparent.rotation_euler.x = radians(-90) bpy.context.scene.collection.objects.link(doodadparent) else: importType = 'WMO' if not givenParent: print('WMO import without given parent, creating..') givenParent = bpy.data.objects.new("WMO parent", None) givenParent.parent = obj givenParent.name = "Doodads" givenParent.rotation_euler = [0, 0, 0] givenParent.rotation_euler.x = radians(-90) bpy.context.scene.collection.objects.link(givenParent) for row in reader: if importType == 'ADT': if 'importedModelIDs' in bpy.context.scene: tempModelIDList = bpy.context.scene['importedModelIDs'] else: tempModelIDList = [] if row['ModelId'] in tempModelIDList: print('Skipping already imported model ' + row['ModelId']) continue else: tempModelIDList.append(row['ModelId']) # ADT CSV if row['Type'] == 'wmo': print('ADT WMO import: ' + row['ModelFile']) # Make WMO parent that holds WMO and doodads parent = bpy.data.objects.new( row['ModelFile'] + " parent", None) parent.parent = wmoparent parent.location = (17066 - float(row['PositionX']), (17066 - float(row['PositionZ'])) * -1, float(row['PositionY'])) parent.rotation_euler = [0, 0, 0] parent.rotation_euler.x += radians( float(row['RotationZ'])) parent.rotation_euler.y += radians( float(row['RotationX'])) parent.rotation_euler.z = radians( (-90 + float(row['RotationY']))) if row['ScaleFactor']: parent.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) bpy.context.scene.collection.objects.link(parent) ## Only import OBJ if model is not yet in scene, otherwise copy existing if row['ModelFile'] not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), parent) else: ## Don't copy WMOs with doodads! if os.path.exists( os.path.join( baseDir, row['ModelFile'].replace( '.obj', '_ModelPlacementInformation.csv')) ): importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), parent) else: originalObject = bpy.data.objects[ row['ModelFile']] importedFile = originalObject.copy() importedFile.data = originalObject.data.copy() bpy.context.scene.collection.objects.link( importedFile) importedFile.parent = parent elif row['Type'] == 'm2': print('ADT M2 import: ' + row['ModelFile']) ## Only import OBJ if model is not yet in scene, otherwise copy existing if row['ModelFile'] not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile'])) else: originalObject = bpy.data.objects[row['ModelFile']] importedFile = originalObject.copy() importedFile.rotation_euler = [0, 0, 0] importedFile.rotation_euler.x = radians(90) bpy.context.scene.collection.objects.link( importedFile) importedFile.parent = doodadparent importedFile.location.x = (17066 - float(row['PositionX'])) importedFile.location.y = ( 17066 - float(row['PositionZ'])) * -1 importedFile.location.z = float(row['PositionY']) importedFile.rotation_euler.x += radians( float(row['RotationZ'])) importedFile.rotation_euler.y += radians( float(row['RotationX'])) importedFile.rotation_euler.z = radians( 90 + float(row['RotationY'])) if row['ScaleFactor']: importedFile.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) bpy.context.scene['importedModelIDs'] = tempModelIDList else: # WMO CSV print('WMO M2 import: ' + row['ModelFile']) if row['ModelFile'] not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile'])) else: originalObject = bpy.data.objects[row['ModelFile']] importedFile = originalObject.copy() bpy.context.scene.collection.objects.link(importedFile) importedFile.location = (float(row['PositionX']) * -1, float(row['PositionY']) * -1, float(row['PositionZ'])) importedFile.rotation_euler = [0, 0, 0] rotQuat = Quaternion( (float(row['RotationW']), float(row['RotationX']), float(row['RotationY']), float(row['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90) rotEul.z += radians(180) importedFile.rotation_euler = rotEul importedFile.parent = givenParent or obj if row['ScaleFactor']: importedFile.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) return obj #objectFile = "D:\\models\\world\\maps\\azeroth\\azeroth_32_32.obj" #objectFile = "D:\\models\\world\\maps\\kultiras\\kultiras_32_29.obj" #objectFile = "D:\\models\\world\\wmo\\kultiras\\human\\8hu_kultiras_seabattlement01.obj" #importWoWOBJ(objectFile)
def CNT(type = 1,res = 1, m=10,n=5,bL=1.56,bR=.1,aR=.2): import bpy from fractions import gcd from math import cos, sin, acos,sqrt,copysign,ceil,floor,pi from mathutils import Vector, Matrix,Quaternion print("Tube: (",m,",",n,"); Radius: ",bL*sqrt(m*m+n*n+m*n)/(2*pi)) cntR = bL*sqrt(m*m+n*n+m*n)/(2*pi) a1=Vector((bL*sqrt(3)/2,bL/2)) a2=Vector((bL*sqrt(3)/2,-bL/2)) x=Vector((bL/sqrt(3),0)) def Lattice2D(i,j,k): return i*a1+j*a2+k*x o = Lattice2D(0,0,0) c = Lattice2D(m,n,0) d = gcd(2*n+m,2*m+n) t = Lattice2D((2*n+m)/d,-(2*m+n)/d,0);print("Unit Length: ",t.magnitude) theta = acos(c.normalized()[0]*copysign(1,c[1])) u = Matrix(((cos(theta),sin(theta)),(-sin(theta),cos(theta)))) def Lattice3D(i,j,k): r = c.magnitude/(2*pi) p = Lattice2D(i,j,k)*u.transposed() return Vector([r*cos(p[0]/r),r*sin(p[0]/r),p[1]]) imax = 2*(n+m); imin = 0 jmax = n; jmin = -(2*m+n) indices = [] for i in range(imin,imax+1): for j in range(jmin,jmax+1): for k in range(2): p = Lattice2D(i,j,k)*u.transposed() if p[0]>=0-bL/5 and p[0]<=c.magnitude-bL/5 and p[1]>=0+bL/10 and p[1]<=t.magnitude+bL/10: indices.append([i,j,k]) print("indices: ",len(indices)) points2D = list(map(lambda x:Lattice2D(x[0],x[1],x[2])*u.transposed(),indices)) print("points2D: ",len(points2D)) bonds2D = [] for i in range(len(indices)): if indices[i][2] == 0: p1=Lattice2D(indices[i][0],indices[i][1],0)*u.transposed() p2=Lattice2D(indices[i][0],indices[i][1],1)*u.transposed() if p2[0]>=0-bL/5 and p2[0]<=c.magnitude+bL/5 and p2[1]>=0-bL/10 and p2[1]<=t.magnitude+bL: bonds2D.append([p1,p2]) p2=Lattice2D(indices[i][0]-1,indices[i][1],1)*u.transposed() if p2[0]>=0-bL/5 and p2[0]<=c.magnitude+bL/5 and p2[1]>=0-bL/10 and p2[1]<=t.magnitude+bL: bonds2D.append([p1,p2]) p2=Lattice2D(indices[i][0],indices[i][1]-1,1)*u.transposed() if p2[0]>=0-bL/5 and p2[0]<=c.magnitude+bL/5 and p2[1]>=0-bL/10 and p2[1]<=t.magnitude+bL: bonds2D.append([p1,p2]) print("bonds2D: ",len(bonds2D)) if type == 0: lyrs = [False]*20; lyrs[3] = True if bpy.data.scenes[0].layers[3] == False: bpy.data.scenes[0].layers[3] = True bpy.ops.object.select_by_layer(extend=False, layers=4) bpy.ops.object.delete() if res < 0: res = 1 if bR > 0: for i in range(len(bonds2D)): temp3D1 = Vector([bonds2D[i][0][0],bonds2D[i][0][1],0]) temp3D2 = Vector([bonds2D[i][1][0],bonds2D[i][1][1],0]) p = (temp3D1+temp3D2)*.5 v = ((temp3D2-temp3D1).normalized()+Vector((0,0,1)))/2 qu = Quaternion((v[0],v[1],v[2]),pi) eu = qu.to_euler() bpy.ops.mesh.primitive_cylinder_add(vertices=res*4,depth=(temp3D2-temp3D1).magnitude*1.05,radius=bR, end_fill_type='NOTHING', location=(p[0], p[1], p[2]), rotation=eu,layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C bonds rendered") if aR > 0: for i in range(len(points2D)): bpy.ops.mesh.primitive_uv_sphere_add(segments=res*4,ring_count=res*2,size=aR,location=(points2D[i][0],points2D[i][1],0),layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C atoms rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0,layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=4) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count=1 bpy.context.active_object.modifiers['Array'].use_relative_offset=False bpy.context.active_object.modifiers['Array'].use_constant_offset=True bpy.context.active_object.modifiers['Array'].constant_offset_displace.y=t.magnitude #bpy.ops.curve.primitive_bezier_circle_add(rotation=(0, pi/2, 0), layers=lyrs) #need to select cnt now. #bpy.ops.object.modifier_add(type='CURVE') else: points3D = list(map(lambda x:Lattice3D(x[0],x[1],x[2]),indices)) print("points3D: ",len(points3D)) bonds3D = [] for i in range(len(indices)): if indices[i][2] == 0: p13D=Lattice3D(indices[i][0],indices[i][1],0) p23D=Lattice3D(indices[i][0],indices[i][1],1) p2=Lattice2D(indices[i][0],indices[i][1],1)*u.transposed() if p2[0]>=0-bL and p2[0]<=c.magnitude+bL and p2[1]>=0-bL and p2[1]<=t.magnitude+bL: bonds3D.append([p13D,p23D]) p23D=Lattice3D(indices[i][0]-1,indices[i][1],1) p2=Lattice2D(indices[i][0]-1,indices[i][1],1)*u.transposed() if p2[0]>=0-bL and p2[0]<=c.magnitude+bL and p2[1]>=0-bL and p2[1]<=t.magnitude+bL: bonds3D.append([p13D,p23D]) p23D=Lattice3D(indices[i][0],indices[i][1]-1,1) p2=Lattice2D(indices[i][0],indices[i][1]-1,1)*u.transposed() if p2[0]>=0-bL and p2[0]<=c.magnitude+bL and p2[1]>=0-bL and p2[1]<=t.magnitude+bL: bonds3D.append([p13D,p23D]) print("bonds3D: ",len(bonds3D)) lyrs = [False]*20; lyrs[1] = True if bpy.data.scenes[0].layers[1] == False: bpy.data.scenes[0].layers[1] = True bpy.ops.object.select_by_layer(extend=False, layers=2) bpy.ops.object.delete() if res < 0: res = 1 if bR > 0: for i in range(len(bonds3D)): p = (bonds3D[i][0]+bonds3D[i][1])*.5 v = ((bonds3D[i][1]-bonds3D[i][0]).normalized()+Vector((0,0,1)))/2 qu = Quaternion((v[0],v[1],v[2]),pi) eu = qu.to_euler() bpy.ops.mesh.primitive_cylinder_add(vertices=res*4,depth=(bonds3D[i][1]-bonds3D[i][0]).magnitude*1.05,radius=bR, end_fill_type='NOTHING', location=(p[0], p[1], p[2]), rotation=eu,layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C bonds rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0,layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=2) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count=1 bpy.context.active_object.modifiers['Array'].use_relative_offset=False bpy.context.active_object.modifiers['Array'].use_constant_offset=True bpy.context.active_object.modifiers['Array'].constant_offset_displace.z=t.magnitude bpy.ops.transform.rotate(value=1.5708, axis=(0, 1, 0)) lyrs = [False]*20; lyrs[2] = True if bpy.data.scenes[0].layers[2] == False: bpy.data.scenes[0].layers[2] = True bpy.ops.object.select_by_layer(extend=False, layers=3) bpy.ops.object.delete() if aR > 0: for i in range(len(points3D)): bpy.ops.mesh.primitive_uv_sphere_add(segments=res*4,ring_count=res*2,size=aR,location=(points3D[i][0],points3D[i][1],points3D[i][2]),layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C atoms rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0,layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=3) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count=1 bpy.context.active_object.modifiers['Array'].use_relative_offset=False bpy.context.active_object.modifiers['Array'].use_constant_offset=True bpy.context.active_object.modifiers['Array'].constant_offset_displace.z=t.magnitude bpy.ops.transform.rotate(value=1.5708, axis=(0, 1, 0))
def export_anim(template_anim, zoffset, rig_name): # output file path = os.path.dirname(os.path.realpath(template_anim)) + '\\' name = os.path.basename(template_anim) if os.path.exists(template_anim): with open(template_anim) as f: xml_string = '\n'.join(f.readlines()) else: xml_string = template obj = bpy.data.objects[rig_name] lara_skin_names = [ 'HIPS', 'LEFT_THIGH', 'LEFT_SHIN', 'LEFT_FOOT', 'RIGHT_THIGH', 'RIGHT_SHIN', 'RIGHT_FOOT', 'TORSO', 'RIGHT_UPPER_ARM', 'RIGHT_FOREARM', 'RIGHT_HAND', 'LEFT_UPPER_ARM', 'LEFT_FOREARM', 'LEFT_HAND', 'HEAD' ] xml_string = xml_string.replace('utf-16', 'utf8') tree = ET.ElementTree(ET.fromstring(xml_string)) root = tree.getroot() # remove template anim file keyframes keyframes_node = tree.find("KeyFrames") for keyframe in keyframes_node.findall("WadKeyFrame"): keyframes_node.remove(keyframe) fcurves = obj.animation_data.action.fcurves keyframes_count = len(fcurves[0].keyframe_points) keyframes_cnt_node = tree.find("EndFrame") keyframes_cnt_node.text = str(keyframes_count) # read keyframes from anim file data = {} for fcurve in fcurves: if "scale" in fcurve.data_path or "HIPS" in fcurve.data_path: # trle does not support scale animation # root motion/rotation is applied to the entire rig, # so discard the hips bone datapath continue else: axis = fcurve.array_index data[(fcurve.data_path, axis)] = [] for i in range(keyframes_count): data[(fcurve.data_path, axis)].append(fcurve.evaluate(i)) # initialize rotations and locations lists for each of the 15 Lara body parts # and keyframes_count keyframes n = len(lara_skin_names) rotations = [[] for _ in range(n)] for i in range(n): for j in range(keyframes_count): rotations[i].append([0, 0, 0, 0]) locations = [[0, 0, 0] for _ in range(keyframes_count)] # For each fcurve for datapath, kf_points in data.items(): if "location" == datapath[0]: # this is the hips location for i in range(keyframes_count): locations[i][ datapath[1]] = kf_points[i] * 512 # 512 is 1m in trle # mixamo animations ground is at the height of the foot pivot point # so let's rise the z offset by the height of the foot mesh if datapath[1] == 2: locations[i][2] += zoffset continue if datapath[0] != 'location' and datapath[0] != 'rotation_euler': # location keyframes are discarded except for the hips bonename = datapath[0].split('"')[1][5:][:-5] else: # the datapath for the hips rotations is rotation_euler bonename = 'HIPS' # save bodyparts rotations in the same order as wad tool axis = datapath[1] idx = lara_skin_names.index(bonename) for i in range(keyframes_count): rotations[idx][i][axis] = kf_points[i] # angles conversion for j, e in enumerate(rotations): if j == lara_skin_names.index('HIPS'): for i in range(keyframes_count): angles = [math.degrees(p) for p in e[i]] rotations[j][i][0] = angles[0] - 90 rotations[j][i][1] = -angles[2] + 90 rotations[j][i][2] = -angles[1] + 180 else: for i in range(keyframes_count): q = Quaternion(e[i]) euler = q.to_euler("ZXY") angles = [math.degrees(e) for e in euler] rotations[j][i][0] = -angles[0] rotations[j][i][1] = angles[1] rotations[j][i][2] = -angles[2] if j == 14 or j == 3 or j == 6: rotations[j][i][0] -= 180 # write output anim file for datapath in range(keyframes_count): wadkf = ET.SubElement(keyframes_node, 'WadKeyFrame') bbox = ET.SubElement(wadkf, 'BoundingBox') minimum = ET.SubElement(bbox, 'Minimum') ET.SubElement(minimum, 'X').text = "0" ET.SubElement(minimum, 'Y').text = "0" ET.SubElement(minimum, 'Z').text = "0" maximum = ET.SubElement(bbox, 'Maximum') ET.SubElement(maximum, 'X').text = "0" ET.SubElement(maximum, 'Y').text = "0" ET.SubElement(maximum, 'Z').text = "0" offset = ET.SubElement(wadkf, 'Offset') x = ET.SubElement(offset, 'X') x.text = '%f' % -locations[datapath][1] y = ET.SubElement(offset, 'Y') y.text = '%f' % locations[datapath][2] z = ET.SubElement(offset, 'Z') z.text = '%f' % locations[datapath][0] angles = ET.SubElement(wadkf, 'Angles') for i in range(n): rot = ET.SubElement(angles, 'WadKeyFrameRotation') rot = ET.SubElement(rot, 'Rotations') x = ET.SubElement(rot, 'X') x.text = '%.6f' % rotations[i][datapath][0] y = ET.SubElement(rot, 'Y') y.text = '%.6f' % rotations[i][datapath][1] z = ET.SubElement(rot, 'Z') z.text = '%.6f' % rotations[i][datapath][2] tree.write(template_anim)
def vectors2euler(vec_ref, vec_actual): rot_axis = vec_ref.cross(vec_actual).normalized() rot_angle = angle_between(vec_actual, vec_ref) quat_rot = Quaternion((rot_axis.x, rot_axis.y, rot_axis.z), rot_angle) euler_rot = quat_rot.to_euler() return euler_rot
def CNT(type=1, res=1, m=10, n=5, bL=1.56, bR=.1, aR=.2): import bpy from fractions import gcd from math import cos, sin, acos, sqrt, copysign, ceil, floor, pi from mathutils import Vector, Matrix, Quaternion print("Tube: (", m, ",", n, "); Radius: ", bL * sqrt(m * m + n * n + m * n) / (2 * pi)) cntR = bL * sqrt(m * m + n * n + m * n) / (2 * pi) a1 = Vector((bL * sqrt(3) / 2, bL / 2)) a2 = Vector((bL * sqrt(3) / 2, -bL / 2)) x = Vector((bL / sqrt(3), 0)) def Lattice2D(i, j, k): return i * a1 + j * a2 + k * x o = Lattice2D(0, 0, 0) c = Lattice2D(m, n, 0) d = gcd(2 * n + m, 2 * m + n) t = Lattice2D((2 * n + m) / d, -(2 * m + n) / d, 0) print("Unit Length: ", t.magnitude) theta = acos(c.normalized()[0] * copysign(1, c[1])) u = Matrix(((cos(theta), sin(theta)), (-sin(theta), cos(theta)))) def Lattice3D(i, j, k): r = c.magnitude / (2 * pi) p = Lattice2D(i, j, k) * u.transposed() return Vector([r * cos(p[0] / r), r * sin(p[0] / r), p[1]]) imax = 2 * (n + m) imin = 0 jmax = n jmin = -(2 * m + n) indices = [] for i in range(imin, imax + 1): for j in range(jmin, jmax + 1): for k in range(2): p = Lattice2D(i, j, k) * u.transposed() if p[0] >= 0 - bL / 5 and p[0] <= c.magnitude - bL / 5 and p[1] >= 0 + bL / 10 and p[1] <= t.magnitude + bL / 10: indices.append([i, j, k]) print("indices: ", len(indices)) points2D = list(map(lambda x: Lattice2D(x[0], x[1], x[2]) * u.transposed(), indices)) print("points2D: ", len(points2D)) bonds2D = [] for i in range(len(indices)): if indices[i][2] == 0: p1 = Lattice2D(indices[i][0], indices[i][1], 0) * u.transposed() p2 = Lattice2D(indices[i][0], indices[i][1], 1) * u.transposed() if p2[0] >= 0 - bL / 5 and p2[0] <= c.magnitude + bL / 5 and p2[1] >= 0 - bL / 10 and p2[1] <= t.magnitude + bL: bonds2D.append([p1, p2]) p2 = Lattice2D(indices[i][0] - 1, indices[i][1], 1) * u.transposed() if p2[0] >= 0 - bL / 5 and p2[0] <= c.magnitude + bL / 5 and p2[1] >= 0 - bL / 10 and p2[1] <= t.magnitude + bL: bonds2D.append([p1, p2]) p2 = Lattice2D(indices[i][0], indices[i][1] - 1, 1) * u.transposed() if p2[0] >= 0 - bL / 5 and p2[0] <= c.magnitude + bL / 5 and p2[1] >= 0 - bL / 10 and p2[1] <= t.magnitude + bL: bonds2D.append([p1, p2]) print("bonds2D: ", len(bonds2D)) if type == 0: lyrs = [False] * 20 lyrs[3] = True if bpy.data.scenes[0].layers[3] == False: bpy.data.scenes[0].layers[3] = True bpy.ops.object.select_by_layer(extend=False, layers=4) bpy.ops.object.delete() if res < 0: res = 1 if bR > 0: for i in range(len(bonds2D)): temp3D1 = Vector([bonds2D[i][0][0], bonds2D[i][0][1], 0]) temp3D2 = Vector([bonds2D[i][1][0], bonds2D[i][1][1], 0]) p = (temp3D1 + temp3D2) * .5 v = ((temp3D2 - temp3D1).normalized() + Vector((0, 0, 1))) / 2 qu = Quaternion((v[0], v[1], v[2]), pi) eu = qu.to_euler() bpy.ops.mesh.primitive_cylinder_add(vertices=res * 4, depth=(temp3D2 - temp3D1).magnitude * 1.05, radius=bR, end_fill_type='NOTHING', location=(p[0], p[1], p[2]), rotation=eu, layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C bonds rendered") if aR > 0: for i in range(len(points2D)): bpy.ops.mesh.primitive_uv_sphere_add(segments=res * 4, ring_count=res * 2, size=aR, location=(points2D[i][0], points2D[i][1], 0), layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C atoms rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0, layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=4) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count = 1 bpy.context.active_object.modifiers['Array'].use_relative_offset = False bpy.context.active_object.modifiers['Array'].use_constant_offset = True bpy.context.active_object.modifiers['Array'].constant_offset_displace.y = t.magnitude # bpy.ops.curve.primitive_bezier_circle_add(rotation=(0, pi/2, 0), layers=lyrs) # need to select cnt now. # bpy.ops.object.modifier_add(type='CURVE') else: points3D = list(map(lambda x: Lattice3D(x[0], x[1], x[2]), indices)) print("points3D: ", len(points3D)) bonds3D = [] for i in range(len(indices)): if indices[i][2] == 0: p13D = Lattice3D(indices[i][0], indices[i][1], 0) p23D = Lattice3D(indices[i][0], indices[i][1], 1) p2 = Lattice2D(indices[i][0], indices[i][1], 1) * u.transposed() if p2[0] >= 0 - bL and p2[0] <= c.magnitude + bL and p2[1] >= 0 - bL and p2[1] <= t.magnitude + bL: bonds3D.append([p13D, p23D]) p23D = Lattice3D(indices[i][0] - 1, indices[i][1], 1) p2 = Lattice2D(indices[i][0] - 1, indices[i][1], 1) * u.transposed() if p2[0] >= 0 - bL and p2[0] <= c.magnitude + bL and p2[1] >= 0 - bL and p2[1] <= t.magnitude + bL: bonds3D.append([p13D, p23D]) p23D = Lattice3D(indices[i][0], indices[i][1] - 1, 1) p2 = Lattice2D(indices[i][0], indices[i][1] - 1, 1) * u.transposed() if p2[0] >= 0 - bL and p2[0] <= c.magnitude + bL and p2[1] >= 0 - bL and p2[1] <= t.magnitude + bL: bonds3D.append([p13D, p23D]) print("bonds3D: ", len(bonds3D)) lyrs = [False] * 20 lyrs[1] = True if bpy.data.scenes[0].layers[1] == False: bpy.data.scenes[0].layers[1] = True bpy.ops.object.select_by_layer(extend=False, layers=2) bpy.ops.object.delete() if res < 0: res = 1 if bR > 0: for i in range(len(bonds3D)): p = (bonds3D[i][0] + bonds3D[i][1]) * .5 v = ((bonds3D[i][1] - bonds3D[i][0]).normalized() + Vector((0, 0, 1))) / 2 qu = Quaternion((v[0], v[1], v[2]), pi) eu = qu.to_euler() bpy.ops.mesh.primitive_cylinder_add(vertices=res * 4, depth=(bonds3D[i][1] - bonds3D[i][0]).magnitude * 1.05, radius=bR, end_fill_type='NOTHING', location=(p[0], p[1], p[2]), rotation=eu, layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C bonds rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0, layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=2) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count = 1 bpy.context.active_object.modifiers['Array'].use_relative_offset = False bpy.context.active_object.modifiers['Array'].use_constant_offset = True bpy.context.active_object.modifiers['Array'].constant_offset_displace.z = t.magnitude bpy.ops.transform.rotate(value=1.5708, axis=(0, 1, 0)) lyrs = [False] * 20 lyrs[2] = True if bpy.data.scenes[0].layers[2] == False: bpy.data.scenes[0].layers[2] = True bpy.ops.object.select_by_layer(extend=False, layers=3) bpy.ops.object.delete() if aR > 0: for i in range(len(points3D)): bpy.ops.mesh.primitive_uv_sphere_add(segments=res * 4, ring_count=res * 2, size=aR, location=(points3D[i][0], points3D[i][1], points3D[i][2]), layers=lyrs) if res > 1: bpy.ops.object.shade_smooth() print("C atoms rendered") bpy.ops.mesh.primitive_uv_sphere_add(size=0, layers=lyrs) bpy.ops.object.select_by_layer(extend=False, layers=3) bpy.ops.object.join() bpy.ops.object.modifier_add(type='ARRAY') bpy.context.active_object.modifiers['Array'].count = 1 bpy.context.active_object.modifiers['Array'].use_relative_offset = False bpy.context.active_object.modifiers['Array'].use_constant_offset = True bpy.context.active_object.modifiers['Array'].constant_offset_displace.z = t.magnitude bpy.ops.transform.rotate(value=1.5708, axis=(0, 1, 0))
def __parse_data(self, context, data, xml): """ Parse an incoming message from the Configurable data service. Also, optionally update the node name map from an XML message. Copy the most recent frame into the scene. """ # Check for changes in the XML channel name definition. if xml != self.__xml: self.__parse_xml(xml) obj = None armature = None # Create a map of data for each connected node. Use the channel name # mapping to look up objects in the Blender scene to apply rotation and # translation data. list = SDK.Format.Configurable(data) for key, item in list.items(): name = self.__name_map.get(key) if name is None: continue # "Body" is the container node for a single skeleton. if name.startswith("Body"): # Either work with independent objects or an armature with # named bones. obj = context.scene.objects.get(name) if obj is not None and 'ARMATURE' == obj.type: armature = obj else: armature = None else: if armature is None: obj = context.scene.objects.get(name) else: obj = armature.pose.bones.get(name) # Rotate. q = Quaternion((item.value(0), item.value(3), item.value(1), item.value(2))) # Translate. t = Vector((item.value(7), item.value(5), item.value(6))) if obj is not None: if 'QUATERNION' == obj.rotation_mode: obj.rotation_quaternion = q else: obj.rotation_euler = q.to_euler(obj.rotation_mode) if armature is None or name.startswith("Hips"): obj.location = t elif self.__debug: print("Missing object named %s" % name) # World space marker. Joint position point cloud with weights. obj = context.scene.objects.get("_".join([name, "Marker"])) if obj is not None: obj.location = t weight = item.value(4) if weight < 0: weight = 0 elif weight > 1: weight = 1 obj.scale.x = obj.scale.y = obj.scale.z = weight + 1
currframe = bpy.context.scene.frame_start currot = startrot center = startcenter for f in range(0, fcount, 1): fprc = f * invfcount osc = abs(sin(TWOPI * fprc)) bpy.context.scene.frame_set(currframe) # Animate location. vecrotate(TWOPI * fprc, axis, pt, rotpt) center = startcenter.lerp(stopcenter, osc) rotpt = rotpt + center current.location = rotpt current.keyframe_insert(data_path='location') # Animate rotation. currot = startrot.slerp(stoprot, jprc * fprc) current.rotation_euler = currot.to_euler() current.keyframe_insert(data_path='rotation_euler') # Animate color. #mat.diffuse_color = colorsys.hsv_to_rgb(jprc, osc, 1.0) #mat.keyframe_insert(data_path='diffuse_color') convertedColor2 = colorsys.hsv_to_rgb(jprc, osc, 1.0) current.color = [convertedColor2[0], convertedColor2[1], convertedColor2[2], 1.0] current.keyframe_insert(data_path='color') currframe += fincr
def load(context, filepath): with ProgressReport(context.window_manager) as progress: progress.enter_substeps(1, "Importing ADT OBJ %r..." % filepath) csvpath = filepath.replace('.obj', '_ModelPlacementInformation.csv') # Coordinate setup ## WoW coordinate sytem # Max Size: 51200 / 3 = 17066,66666666667 # Map Size: Max Size * 2 = 34133,33333333333 # ADT Size: Map Size / 64 = 533,3333333333333 max_size = 51200 / 3 map_size = max_size * 2 adt_size = map_size / 64 base_folder, adtname = os.path.split(filepath) adtsplit = adtname.split("_") mapname = adtsplit[0] map_x = int(adtsplit[1]) map_y = int(adtsplit[2].replace(".obj", "")) print(mapname) print(map_x) print(map_y) offset_x = adt_size * map_x offset_y = adt_size * map_y print(offset_x) print(offset_y) # Import ADT bpy.ops.import_scene.obj(filepath=filepath) bpy.ops.object.add(type='EMPTY') doodadparent = bpy.context.active_object doodadparent.parent = bpy.data.objects[mapname + '_' + str(map_x) + '_' + str(map_y)] doodadparent.name = "Doodads" doodadparent.rotation_euler = [0, 0, 0] doodadparent.rotation_euler.x = radians(-90) bpy.ops.object.add(type='EMPTY') wmoparent = bpy.context.active_object wmoparent.parent = bpy.data.objects[mapname + '_' + str(map_x) + '_' + str(map_y)] wmoparent.name = "WMOs" wmoparent.rotation_euler = [0, 0, 0] wmoparent.rotation_euler.x = radians(-90) # Make object active # bpy.context.scene.objects.active = obj # Read doodad definitions file with open(csvpath) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: doodad_path, doodad_filename = os.path.split(filepath) newpath = os.path.join(doodad_path, row['ModelFile']) if row['Type'] == 'wmo': bpy.ops.object.add(type='EMPTY') parent = bpy.context.active_object parent.name = row['ModelFile'] parent.parent = wmoparent parent.location = (17066 - float(row['PositionX']), (17066 - float(row['PositionZ'])) * -1, float(row['PositionY'])) parent.rotation_euler = [0, 0, 0] #obj.rotation_euler.x += (radians(90 + float(row['RotationX']))) # TODO #obj.rotation_euler.y -= radians(float(row['RotationY'])) # TODO parent.rotation_euler.z = radians( (-90 + float(row['RotationY']))) bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] # Put ADT rotations in here for obj in obj_objects: obj.parent = parent wmocsvpath = newpath.replace( '.obj', '_ModelPlacementInformation.csv') # Read WMO doodads definitions file with open(wmocsvpath) as wmocsvfile: wmoreader = csv.DictReader(wmocsvfile, delimiter=';') for wmorow in wmoreader: wmodoodad_path, wmodoodad_filename = os.path.split( filepath) wmonewpath = os.path.join(wmodoodad_path, wmorow['ModelFile']) # Import the doodad bpy.ops.import_scene.obj(filepath=wmonewpath) # Select the imported doodad wmoobj_objects = bpy.context.selected_objects[:] for wmoobj in wmoobj_objects: # Prepend name wmoobj.name = "(" + wmorow[ 'DoodadSet'] + ") " + wmoobj.name # Set parent wmoobj.parent = parent # Set position wmoobj.location = (float(wmorow['PositionX']) * -1, float(wmorow['PositionY']) * -1, float(wmorow['PositionZ'])) # Set rotation rotQuat = Quaternion( (float(wmorow['RotationW']), float(wmorow['RotationX']), float(wmorow['RotationY']), float(wmorow['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90) #rotEul.z += radians(90); wmoobj.rotation_euler = rotEul # Set scale if wmorow['ScaleFactor']: wmoobj.scale = (float( wmorow['ScaleFactor']), float( wmorow['ScaleFactor']), float( wmorow['ScaleFactor'])) else: print("m2") bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: # Set parent obj.parent = doodadparent # Set location obj.location.x = (17066 - float(row['PositionX'])) obj.location.y = (17066 - float(row['PositionZ'])) * -1 obj.location.z = float(row['PositionY']) obj.rotation_euler.x += radians(float( row['RotationZ'])) obj.rotation_euler.y += radians(float( row['RotationX'])) obj.rotation_euler.z = radians( 90 + float(row['RotationY'])) # okay # Set scale if row['ScaleFactor']: obj.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) progress.leave_substeps("Finished importing: %r" % filepath) return {'FINISHED'}
def load(context, filepath ): with ProgressReport(context.window_manager) as progress: progress.enter_substeps(1, "Importing ADT OBJ %r..." % filepath) csvpath = filepath.replace('.obj', '_ModelPlacementInformation.csv') # Coordinate setup ## WoW coordinate sytem # Max Size: 51200 / 3 = 17066,66666666667 # Map Size: Max Size * 2 = 34133,33333333333 # ADT Size: Map Size / 64 = 533,3333333333333 max_size = 51200 / 3 map_size = max_size * 2 adt_size = map_size / 64 base_folder, adtname = os.path.split(filepath) adtsplit = adtname.split("_") mapname = adtsplit[0] map_x = int(adtsplit[1]) map_y = int(adtsplit[2].replace(".obj", "")) print(mapname) print(map_x) print(map_y) offset_x = adt_size * map_x offset_y = adt_size * map_y print(offset_x) print(offset_y) # Import ADT bpy.ops.import_scene.obj(filepath=filepath) bpy.ops.object.add(type='EMPTY') doodadparent = bpy.context.active_object doodadparent.parent = bpy.data.objects[mapname + '_' + str(map_x) + '_' + str(map_y)] doodadparent.name = "Doodads" doodadparent.rotation_euler = [0, 0, 0] doodadparent.rotation_euler.x = radians(-90) bpy.ops.object.add(type='EMPTY') wmoparent = bpy.context.active_object wmoparent.parent = bpy.data.objects[mapname + '_' + str(map_x) + '_' + str(map_y)] wmoparent.name = "WMOs" wmoparent.rotation_euler = [0, 0, 0] wmoparent.rotation_euler.x = radians(-90) # Make object active # bpy.context.scene.objects.active = obj # Read doodad definitions file with open(csvpath) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: doodad_path, doodad_filename = os.path.split(filepath) newpath = os.path.join(doodad_path, row['ModelFile']) if row['Type'] == 'wmo': bpy.ops.object.add(type='EMPTY') parent = bpy.context.active_object parent.name = row['ModelFile'] parent.parent = wmoparent parent.location = (17066 - float(row['PositionX']), (17066 - float(row['PositionZ'])) * -1, float(row['PositionY'])) parent.rotation_euler = [0, 0, 0] #obj.rotation_euler.x += (radians(90 + float(row['RotationX']))) # TODO #obj.rotation_euler.y -= radians(float(row['RotationY'])) # TODO parent.rotation_euler.z = radians((-90 + float(row['RotationY']))) if row['ScaleFactor']: parent.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] # Put ADT rotations in here for obj in obj_objects: obj.parent = parent wmocsvpath = newpath.replace('.obj', '_ModelPlacementInformation.csv') # Read WMO doodads definitions file with open(wmocsvpath) as wmocsvfile: wmoreader = csv.DictReader(wmocsvfile, delimiter=';') for wmorow in wmoreader: wmodoodad_path, wmodoodad_filename = os.path.split(filepath) wmonewpath = os.path.join(wmodoodad_path, wmorow['ModelFile']) # Import the doodad if(os.path.exists(wmonewpath)): bpy.ops.import_scene.obj(filepath=wmonewpath) # Select the imported doodad wmoobj_objects = bpy.context.selected_objects[:] for wmoobj in wmoobj_objects: # Prepend name wmoobj.name = "(" + wmorow['DoodadSet'] + ") " + wmoobj.name # Set parent wmoobj.parent = parent # Set position wmoobj.location = (float(wmorow['PositionX']) * -1, float(wmorow['PositionY']) * -1, float(wmorow['PositionZ'])) # Set rotation rotQuat = Quaternion((float(wmorow['RotationW']), float(wmorow['RotationX']), float(wmorow['RotationY']), float(wmorow['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90); rotEul.z += radians(180); wmoobj.rotation_euler = rotEul # Set scale if wmorow['ScaleFactor']: wmoobj.scale = (float(wmorow['ScaleFactor']), float(wmorow['ScaleFactor']), float(wmorow['ScaleFactor'])) # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) else: if(os.path.exists(newpath)): bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: # Set parent obj.parent = doodadparent # Set location obj.location.x = (17066 - float(row['PositionX'])) obj.location.y = (17066 - float(row['PositionZ'])) * -1 obj.location.z = float(row['PositionY']) obj.rotation_euler.x += radians(float(row['RotationZ'])) obj.rotation_euler.y += radians(float(row['RotationX'])) obj.rotation_euler.z = radians(90 + float(row['RotationY'])) # okay # Set scale if row['ScaleFactor']: obj.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) # Set doodad and WMO parent to 0 wmoparent.location = (0, 0, 0) doodadparent.location = (0, 0, 0) print("Deduplicating and cleaning up materials!") # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) progress.leave_substeps("Finished importing: %r" % filepath) return {'FINISHED'}
def importWoWOBJ(objectFile, givenParent=None, settings=None): baseDir, fileName = os.path.split(objectFile) print('Parsing OBJ: ' + fileName) ### OBJ wide material_libs = set() mtlfile = '' verts = [] normals = [] uvs = [] meshes = [] ### Per group class OBJMesh: def __init__(self): self.usemtl = '' self.name = '' self.verts = set() self.faces = [] curMesh = OBJMesh() meshIndex = -1 with open(objectFile, 'rb') as f: for line in f: line_split = line.split() if not line_split: continue line_start = line_split[0] if line_start == b'mtllib': mtlfile = line_split[1] elif line_start == b'v': verts.append([float(v) for v in line_split[1:]]) elif line_start == b'vn': normals.append([float(v) for v in line_split[1:]]) elif line_start.startswith(b'vt'): layer_index = 0 if len(line_start) > 2: line_str = line_start.decode('utf8') layer_index = int(line_str[-1]) - 1 if len(uvs) <= layer_index: uvs.append([]) uvs[layer_index].append([float(v) for v in line_split[1:]]) elif line_start == b'f': line_split = line_split[1:] fv = [int(v.split(b'/')[0]) for v in line_split] meshes[meshIndex].faces.append((fv[0], fv[1], fv[2])) meshes[meshIndex].verts.update([i - 1 for i in fv]) elif line_start == b'g': meshIndex += 1 meshes.append(OBJMesh()) meshes[meshIndex].name = line_split[1].decode('utf-8') elif line_start == b'usemtl': meshes[meshIndex].usemtl = line_split[1].decode('utf-8') # Defaults to master collection if no collection exists. collection = bpy.context.view_layer.active_layer_collection.collection.objects ## Materials file (.mtl) materials = dict() matname = '' matfile = '' if mtlfile != '': with open(os.path.join(baseDir, mtlfile.decode('utf-8')), 'r') as f: for line in f: line_split = line.split() if not line_split: continue line_start = line_split[0] if line_start == 'newmtl': matname = line_split[1] elif line_start == 'map_Kd': matfile = line_split[1] materials[matname] = os.path.join(baseDir, matfile) if bpy.ops.object.select_all.poll(): bpy.ops.object.select_all(action='DESELECT') # TODO: Better handling for dupes? objname = os.path.basename(objectFile) if objname in bpy.data.objects: objindex = 1 newname = objname while (newname in bpy.data.objects): newname = objname + '.' + str(objindex).rjust(3, '0') objindex += 1 newmesh = bpy.data.meshes.new(objname) obj = bpy.data.objects.new(objname, newmesh) # Create a new material instance for each material entry. if settings.importTextures: for materialName, textureLocation in materials.items(): material = None if materialName in bpy.data.materials: material = bpy.data.materials[materialName] else: material = bpy.data.materials.new(name=materialName) material.use_nodes = True material.blend_method = 'CLIP' node_tree = material.node_tree nodes = node_tree.nodes # Note on socket reference localization: # Unlike nodes, sockets can be referenced in English regardless of localization. # This will break if the user sets the socket names to any non-default value. # Create new Principled BSDF and Image Texture nodes. principled = None outNode = None for node in nodes: if not principled and node.type == 'BSDF_PRINCIPLED': principled = node if not outNode and node.type == 'OUTPUT_MATERIAL': outNode = node if principled and outNode: break # If there is no Material Output node, create one. if not outNode: outNode = nodes.new('ShaderNodeOutputMaterial') # If there is no default Principled BSDF node, create one and link it to material output. if not principled: principled = nodes.new('ShaderNodeBsdfPrincipled') node_tree.links.new(principled.outputs['BSDF'], outNode.inputs['Surface']) # Create a new Image Texture node. image = nodes.new('ShaderNodeTexImage') # Load the image file itself if necessary. imageName = os.path.basename(textureLocation) if not imageName in bpy.data.images: bpy.data.images.load(textureLocation) image.image = bpy.data.images[imageName] node_tree.links.new(image.outputs['Color'], principled.inputs['Base Color']) image.image.alpha_mode = 'CHANNEL_PACKED' if settings.useAlpha: node_tree.links.new(image.outputs['Alpha'], principled.inputs['Alpha']) # Set the specular value to 0 by default. principled.inputs['Specular'].default_value = 0 obj.data.materials.append(bpy.data.materials[materialName]) ## Meshes bm = bmesh.new() i = 0 for v in verts: vert = bm.verts.new(v) vert.normal = normals[i] i = i + 1 bm.verts.ensure_lookup_table() bm.verts.index_update() for mesh in meshes: exampleFaceSet = False for face in mesh.faces: try: ## TODO: Must be a better way to do this, this is already much faster than doing material every face, but still. if exampleFaceSet == False: bm.faces.new((bm.verts[face[0] - 1], bm.verts[face[1] - 1], bm.verts[face[2] - 1])) bm.faces.ensure_lookup_table() if mesh.usemtl: bm.faces[-1].material_index = obj.data.materials.find( mesh.usemtl) bm.faces[-1].smooth = True exampleFace = bm.faces[-1] exampleFaceSet = True else: ## Use example face if set to speed up material copy! bm.faces.new((bm.verts[face[0] - 1], bm.verts[face[1] - 1], bm.verts[face[2] - 1]), exampleFace) except ValueError: ## TODO: Duplicate faces happen for some reason pass for layer_index, layer in enumerate(uvs): uv_name = layer_index > 0 and ('UV' + str(layer_index + 1) + 'Map') or 'UVMap' uv_layer = bm.loops.layers.uv.new(uv_name) for face in bm.faces: for loop in face.loops: loop[uv_layer].uv = layer[loop.vert.index] bm.to_mesh(newmesh) bm.free() # needed to have a mesh before we can create vertex groups, so do that now if settings.createVertexGroups: for mesh in sorted(meshes, key=lambda m: m.name.lower()): vg = obj.vertex_groups.new(name=f"{mesh.name}") vg.add(list(mesh.verts), 1.0, "REPLACE") ## Rotate object the right way obj.rotation_euler = [0, 0, 0] obj.rotation_euler.x = radians(90) collection.link(obj) obj.select_set(True) ## WoW coordinate system max_size = 51200 / 3 map_size = max_size * 2 adt_size = map_size / 64 ## Import doodads and/or WMOs csvPath = objectFile.replace('.obj', '_ModelPlacementInformation.csv') use_csv = settings.importWMO or settings.importM2 or settings.importWMOSets or settings.importGOBJ if use_csv and os.path.exists(csvPath): with open(csvPath) as csvFile: reader = csv.DictReader(csvFile, delimiter=';') if 'Type' in reader.fieldnames: importType = 'ADT' wmoparent = None if settings.importWMO: wmoparent = bpy.data.objects.new('WMOs', None) wmoparent.parent = obj wmoparent.name = 'WMOs' wmoparent.rotation_euler = [0, 0, 0] wmoparent.rotation_euler.x = radians(-90) collection.link(wmoparent) doodadparent = None if settings.importM2: doodadparent = bpy.data.objects.new('Doodads', None) doodadparent.parent = obj doodadparent.name = 'Doodads' doodadparent.rotation_euler = [0, 0, 0] doodadparent.rotation_euler.x = radians(-90) collection.link(doodadparent) gobjparent = None if settings.importGOBJ: gobjparent = bpy.data.objects.new('GameObjects', None) gobjparent.parent = obj gobjparent.name = 'GameObjects' gobjparent.rotation_euler = [0, 0, 0] gobjparent.rotation_euler.x = radians(-90) collection.link(gobjparent) else: importType = 'WMO' if not givenParent: print('WMO import without given parent, creating..') if settings.importWMOSets: givenParent = bpy.data.objects.new('WMO parent', None) givenParent.parent = obj givenParent.name = 'Doodads' givenParent.rotation_euler = [0, 0, 0] givenParent.rotation_euler.x = radians(-90) collection.link(givenParent) for row in reader: if importType == 'ADT': if 'importedModelIDs' in bpy.context.scene: tempModelIDList = bpy.context.scene['importedModelIDs'] else: tempModelIDList = [] if row['ModelId'] in tempModelIDList: if not settings.allowDuplicates: print('Skipping already imported model ' + row['ModelId']) continue else: tempModelIDList.append(row['ModelId']) # ADT CSV if row['Type'] == 'wmo' and settings.importWMO: print('ADT WMO import: ' + row['ModelFile']) # Make WMO parent that holds WMO and doodads parent = bpy.data.objects.new( os.path.basename(row['ModelFile']) + ' parent', None) parent.parent = wmoparent parent.location = ( max_size - float(row['PositionX']), (max_size - float(row['PositionZ'])) * -1, float(row['PositionY'])) parent.rotation_euler = [0, 0, 0] parent.rotation_euler.x += radians( float(row['RotationZ'])) parent.rotation_euler.y += radians( float(row['RotationX'])) parent.rotation_euler.z = radians( (90 + float(row['RotationY']))) if row['ScaleFactor']: parent.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) collection.link(parent) ## Only import OBJ if model is not yet in scene, otherwise copy existing if os.path.basename( row['ModelFile']) not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), parent, settings) else: ## Don't copy WMOs with doodads! if os.path.exists( os.path.join( baseDir, row['ModelFile'].replace( '.obj', '_ModelPlacementInformation.csv')) ): importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), parent, settings) else: originalObject = bpy.data.objects[ os.path.basename(row['ModelFile'])] importedFile = originalObject.copy() importedFile.data = originalObject.data.copy() collection.link(importedFile) importedFile.parent = parent elif row['Type'] == 'm2' and settings.importM2: print('ADT M2 import: ' + row['ModelFile']) ## Only import OBJ if model is not yet in scene, otherwise copy existing if os.path.basename( row['ModelFile']) not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), None, settings) else: originalObject = bpy.data.objects[os.path.basename( row['ModelFile'])] importedFile = originalObject.copy() importedFile.rotation_euler = [0, 0, 0] importedFile.rotation_euler.x = radians(90) collection.link(importedFile) importedFile.parent = doodadparent importedFile.location.x = (max_size - float(row['PositionX'])) importedFile.location.y = ( max_size - float(row['PositionZ'])) * -1 importedFile.location.z = float(row['PositionY']) importedFile.rotation_euler.x += radians( float(row['RotationZ'])) importedFile.rotation_euler.y += radians( float(row['RotationX'])) importedFile.rotation_euler.z = radians( 90 + float(row['RotationY'])) if row['ScaleFactor']: importedFile.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) elif row['Type'] == 'gobj' and settings.importGOBJ: if os.path.basename( row['ModelFile']) not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), None, settings) else: originalObject = bpy.data.objects[os.path.basename( row['ModelFile'])] importedFile = originalObject.copy() importedFile.rotation_euler = [0, 0, 0] importedFile.rotation_euler.x = radians(90) collection.link(importedFile) importedFile.parent = gobjparent importedFile.location = (float(row['PositionY']), -float(row['PositionX']), float(row['PositionZ'])) rotQuat = Quaternion( (float(row['RotationX']), float(row['RotationY']), -float(row['RotationZ']), float(row['RotationW']))) rotEul = rotQuat.to_euler() importedFile.rotation_euler = rotEul if row['ScaleFactor']: importedFile.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) bpy.context.scene['importedModelIDs'] = tempModelIDList elif settings.importWMOSets: # WMO CSV print('WMO M2 import: ' + row['ModelFile']) if os.path.basename( row['ModelFile']) not in bpy.data.objects: importedFile = importWoWOBJ( os.path.join(baseDir, row['ModelFile']), None, settings) else: originalObject = bpy.data.objects[os.path.basename( row['ModelFile'])] importedFile = originalObject.copy() collection.link(importedFile) importedFile.location = (float(row['PositionX']), float(row['PositionY']), float(row['PositionZ'])) importedFile.rotation_euler = [0, 0, 0] rotQuat = Quaternion( (float(row['RotationW']), float(row['RotationX']), float(row['RotationY']), float(row['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90) importedFile.rotation_euler = rotEul importedFile.parent = givenParent or obj if row['ScaleFactor']: importedFile.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) return obj
def load(context, filepath): csvpath = filepath.replace('.obj', '_ModelPlacementInformation.csv') # Coordinate setup ## WoW coordinate sytem # Max Size: 51200 / 3 = 17066,66666666667 # Map Size: Max Size * 2 = 34133,33333333333 # ADT Size: Map Size / 64 = 533,3333333333333 max_size = 51200 / 3 map_size = max_size * 2 adt_size = map_size / 64 base_folder, adtname = os.path.split(filepath) adtsplit = adtname.split("_") mapname = adtsplit[0] map_x = int(adtsplit[1]) map_y = int(adtsplit[2].replace(".obj", "")) print(mapname) print(map_x) print(map_y) offset_x = adt_size * map_x offset_y = adt_size * map_y print(offset_x) print(offset_y) # Import ADT bpy.ops.import_scene.obj(filepath=filepath) adtObject = bpy.data.objects[mapname + '_' + str(map_x) + '_' + str(map_y)] # Make shader sane and fix UV clamping (Kruithne) for mat_slot in adtObject.material_slots: node_tree = mat_slot.material.node_tree nodes = node_tree.nodes for node in nodes: if node.name != 'Image Texture' and node.name != 'Material Output' and node.name != 'Diffuse BSDF': node_tree.nodes.remove(node) node_tree.links.new(nodes['Image Texture'].outputs[0], nodes['Diffuse BSDF'].inputs[0]) node_tree.links.new(nodes['Diffuse BSDF'].outputs[0], nodes['Material Output'].inputs[0]) imageNode = nodes['Image Texture'] imageNode.extension = 'EXTEND' imageNode.image.use_alpha = False bpy.ops.object.add(type='EMPTY') doodadparent = bpy.context.active_object doodadparent.parent = adtObject doodadparent.name = "Doodads" doodadparent.rotation_euler = [0, 0, 0] doodadparent.rotation_euler.x = radians(-90) bpy.ops.object.add(type='EMPTY') wmoparent = bpy.context.active_object wmoparent.parent = adtObject wmoparent.name = "WMOs" wmoparent.rotation_euler = [0, 0, 0] wmoparent.rotation_euler.x = radians(-90) # Make object active # bpy.context.scene.objects.active = obj # Read doodad definitions file with open(csvpath) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: doodad_path, doodad_filename = os.path.split(filepath) newpath = os.path.join(doodad_path, row['ModelFile']) if row['Type'] == 'wmo': bpy.ops.object.add(type='EMPTY') parent = bpy.context.active_object parent.name = row['ModelFile'] parent.parent = wmoparent parent.location = (17066 - float(row['PositionX']), (17066 - float(row['PositionZ'])) * -1, float(row['PositionY'])) parent.rotation_euler = [0, 0, 0] #obj.rotation_euler.x += (radians(90 + float(row['RotationX']))) # TODO #obj.rotation_euler.y -= radians(float(row['RotationY'])) # TODO parent.rotation_euler.z = radians( (-90 + float(row['RotationY']))) if row['ScaleFactor']: parent.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] # Put ADT rotations in here for obj in obj_objects: obj.parent = parent wmocsvpath = newpath.replace('.obj', '_ModelPlacementInformation.csv') # Read WMO doodads definitions file with open(wmocsvpath) as wmocsvfile: wmoreader = csv.DictReader(wmocsvfile, delimiter=';') for wmorow in wmoreader: wmodoodad_path, wmodoodad_filename = os.path.split( filepath) wmonewpath = os.path.join(wmodoodad_path, wmorow['ModelFile']) # Import the doodad if (os.path.exists(wmonewpath)): bpy.ops.import_scene.obj(filepath=wmonewpath) # Select the imported doodad wmoobj_objects = bpy.context.selected_objects[:] for wmoobj in wmoobj_objects: # Prepend name wmoobj.name = "(" + wmorow[ 'DoodadSet'] + ") " + wmoobj.name # Set parent wmoobj.parent = parent # Set position wmoobj.location = (float(wmorow['PositionX']) * -1, float(wmorow['PositionY']) * -1, float(wmorow['PositionZ'])) # Set rotation rotQuat = Quaternion( (float(wmorow['RotationW']), float(wmorow['RotationX']), float(wmorow['RotationY']), float(wmorow['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90) rotEul.z += radians(180) wmoobj.rotation_euler = rotEul # Set scale if wmorow['ScaleFactor']: wmoobj.scale = (float( wmorow['ScaleFactor']), float( wmorow['ScaleFactor']), float( wmorow['ScaleFactor'])) # Duplicate material removal script by Kruithne # Merge all duplicate materials # for obj in bpy.context.scene.objects: # if obj.type == 'MESH': # i = 0 # for mat_slot in obj.material_slots: # mat = mat_slot.material # obj.material_slots[i].material = bpy.data.materials[mat.name.split('.')[0]] # i += 1 # # Cleanup unused materials # for img in bpy.data.images: # if not img.users: # bpy.data.images.remove(img) else: if (os.path.exists(newpath)): bpy.ops.import_scene.obj(filepath=newpath) obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: # Set parent obj.parent = doodadparent # Set location obj.location.x = (17066 - float(row['PositionX'])) obj.location.y = (17066 - float(row['PositionZ'])) * -1 obj.location.z = float(row['PositionY']) obj.rotation_euler.x += radians(float( row['RotationZ'])) obj.rotation_euler.y += radians(float( row['RotationX'])) obj.rotation_euler.z = radians( 90 + float(row['RotationY'])) # okay # Set scale if row['ScaleFactor']: obj.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) # Set doodad and WMO parent to 0 wmoparent.location = (0, 0, 0) doodadparent.location = (0, 0, 0) print("Deduplicating and cleaning up materials!") # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[ mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) return {'FINISHED'}
def invoke(self, context, event): if context.scene.awc_is_preview: bpy.ops.armature.walk_cycle_preview('INVOKE_DEFAULT') rig = context.object awc = rig.data.aut_walk_cycle torso = awc.torso l_foot = awc.l_foot_ik r_foot = awc.r_foot_ik torso_obj = rig.pose.bones[torso] torso_dat = rig.data.bones[torso] mtdat = torso_dat.matrix_local.copy() step_by_frames = awc.step_by_frames if step_by_frames: dist = awc.step_frames / 2 else: dist = awc.step / 4 fr_start = awc.frame_start fr_end = awc.frame_end if awc.anim: try: fc = rig.animation_data.action.fcurves except Exception as e: print(e) return {'FINISHED'} rot_mode = torso_obj.rotation_mode if rot_mode == 'QUATERNION': rtype = '.rotation_quaternion' elif rot_mode == 'AXIS_ANGLE': rtype = '.rotation_axis_angle' else: rtype = '.rotation_euler' dp = 'pose.bones["%s"]' % torso fc_loc = {} fc_rot = {} for _fc in fc: if dp in _fc.data_path: ldp = _fc.data_path type = ldp[ldp.rfind("."):] if type == '.location': fc_loc[_fc.array_index] = _fc elif type == rtype: fc_rot[_fc.array_index] = _fc seq = [] for fr in range(fr_start, fr_end + 1): vec = Vector((fc_loc[0].evaluate(fr) if 0 in fc_loc else 0, fc_loc[1].evaluate(fr) if 1 in fc_loc else 0, fc_loc[2].evaluate(fr) if 2 in fc_loc else 0)) if fr in {fr_start, fr_end}: d = dist else: if step_by_frames: d = fr - lframe else: d = (lvec - vec).length if d >= dist: if rot_mode == 'QUATERNION': rot = Quaternion( (fc_rot[0].evaluate(fr) if 0 in fc_rot else 1, fc_rot[1].evaluate(fr) if 1 in fc_rot else 0, fc_rot[2].evaluate(fr) if 2 in fc_rot else 0, fc_rot[3].evaluate(fr) if 3 in fc_rot else 0)).normalized() elif rot_mode == 'AXIS_ANGLE': rot = Quaternion( (fc_rot[1].evaluate(fr) if 1 in fc_rot else 0, fc_rot[2].evaluate(fr) if 2 in fc_rot else 1, fc_rot[3].evaluate(fr) if 3 in fc_rot else 0), fc_rot[0].evaluate(fr) if 0 in fc_rot else 0).normalized() else: rot = Euler( (fc_rot[0].evaluate(fr) if 0 in fc_rot else 0, fc_rot[1].evaluate(fr) if 1 in fc_rot else 0, fc_rot[2].evaluate(fr) if 2 in fc_rot else 0), rot_mode) mt = Matrix.Translation(vec) mr = rot.to_matrix() mbasis = mt * mr.to_4x4() mat = mtdat * mbasis * mtdat.inverted() seq.append((fr, mat)) lvec = vec lframe = fr f_curves = {} for col_bone in set(awc.new_bones.keys()): if col_bone: dp_loc = 'pose.bones["%s"].location' % col_bone rot_mode = rig.pose.bones[col_bone].rotation_mode if rot_mode == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % col_bone size = 4 elif rot_mode == 'AXIS_ANGLE': dp_rot = 'pose.bones["%s"].rotation_axis_angle' % col_bone size = 4 else: dp_rot = 'pose.bones["%s"].rotation_euler' % col_bone size = 3 f_curves[col_bone] = (find_remove_keys( fc, dp_loc, 3, fr_start, fr_end), find_remove_keys( fc, dp_rot, size, fr_start, fr_end)) ### feet ### l_foot_ik = rig.pose.bones[l_foot] r_foot_ik = rig.pose.bones[r_foot] dp_loc = 'pose.bones["%s"].location' % l_foot fc_lf = find_remove_keys(fc, dp_loc, 3, fr_start, fr_end) rot_modl = l_foot_ik.rotation_mode if rot_modl == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % l_foot size = 4 elif rot_modl == 'AXIS_ANGLE': dp_rot = 'pose.bones["%s"].rotation_axis_angle' % l_foot size = 4 else: dp_rot = 'pose.bones["%s"].rotation_euler' % l_foot size = 3 fcqua_lf = find_remove_keys(fc, dp_rot, size, fr_start, fr_end) dp_loc = 'pose.bones["%s"].location' % r_foot fc_rf = find_remove_keys(fc, dp_loc, 3, fr_start, fr_end) rot_modr = r_foot_ik.rotation_mode if rot_modr == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % r_foot size = 4 elif rot_modr == 'AXIS_ANGLE': dp_rot = 'pose.bones["%s"].rotation_axis_angle' % r_foot size = 4 else: dp_rot = 'pose.bones["%s"].rotation_euler' % r_foot size = 3 fcqua_rf = find_remove_keys(fc, dp_rot, size, fr_start, fr_end) del size, dp_loc, dp_rot lf_dat = rig.data.bones[l_foot] rf_dat = rig.data.bones[r_foot] #m_lo_lf = lf_dat.matrix_local.copy() #m_lo_rf = rf_dat.matrix_local.copy() mdef = lf_dat.matrix_local.copy(), rf_dat.matrix_local.copy() use_local = lf_dat.use_local_location, rf_dat.use_local_location fc_loc = fc_lf, fc_rf fc_qua = fcqua_lf, fcqua_rf rot_mode = rot_modl, rot_modr up_axis = awc.up_axis.copy() up_axis.rotate(mtdat) side_axis = awc.side_axis.copy() side_axis.rotate(mtdat) openness = awc.openness amp = awc.amp ant = 1 - awc.anticipation fo_rot = awc.foot_rot right = True for i, tp in enumerate(seq): fr_f = i % 2 # 01010101010101010101 fr, mat = tp try: fr2, mat2 = seq[i + 1] except: fr2, mat2 = seq[i] try: fr3, mat3 = seq[i + 2] except: fr3, mat3 = fr2, mat2 #obj_empty = bpy.data.objects.new("Test", None) #context.scene.objects.link(obj_empty) #obj_empty.matrix_world = mat #obj_empty.empty_draw_type = 'ARROWS' #obj_empty.empty_draw_size = .3 if not fr_f: right = not right # 0011001100110011001100 matf = mat.lerp(mat3, ant) for f in range(2): #matc = matf.copy() mat_loc = mdef[f].copy() if f - right: # foot down mat_loc.translation += (2 * f - 1) * openness * side_axis #mat_glo = matf * mat_loc mat_bas = mdef[f].inverted() * matf * mat_loc if not use_local[f]: mat_bas.translation.rotate(mdef[f]) #mat_bas = Matrix.Translation(-mdef[f].translation) * matf * Matrix.Translation(mdef[f].translation + (2*f - 1) * openness * side_axis) loc, qua, _ = mat_bas.decompose() # LOCATION DW for ax, fcl in enumerate(fc_loc[f]): fcl.keyframe_points.add(2) fcl.keyframe_points[ -2].interpolation = 'BEZIER' fcl.keyframe_points[ -2].handle_right_type = 'VECTOR' fcl.keyframe_points[ -2].handle_left_type = 'VECTOR' fcl.keyframe_points[-2].co = fr, loc[ax] fcl.keyframe_points[ -1].interpolation = 'BEZIER' fcl.keyframe_points[ -1].handle_right_type = 'VECTOR' fcl.keyframe_points[ -1].handle_left_type = 'VECTOR' fcl.keyframe_points[-1].co = fr3, loc[ax] # ROTATION DW axis = mdef[f].inverted( ) * side_axis # FOOT LOCAL SIDE_AXIS rot1 = qua * Quaternion(axis, ant * fo_rot) rot2 = qua * Quaternion(axis, (ant - 1) * fo_rot) dif_fr = fr3 - fr f1 = fr3 - dif_fr * (1 - ant / 2) f2 = fr3 - dif_fr * (1 - (2 + ant) / 3) if rot_mode[f] == 'QUATERNION': pass elif rot_mode[f] == 'AXIS_ANGLE': qua = qua.to_axis_angle() qua = qua[1], qua[0][0], qua[0][1], qua[0][2] rot1 = rot1.to_axis_angle() rot1 = rot1[1], rot1[0][0], rot1[0][1], rot1[ 0][2] rot2 = rot2.to_axis_angle() rot2 = rot2[1], rot2[0][0], rot2[0][1], rot2[ 0][2] else: qua = qua.to_euler(rot_mode[f]) rot1 = rot1.to_euler(rot_mode[f], qua) rot2 = rot2.to_euler(rot_mode[f], qua) for ax, fcq in enumerate(fc_qua[f]): fcq.keyframe_points.add(4) fcq.keyframe_points[ -4].interpolation = 'LINEAR' fcq.keyframe_points[ -3].interpolation = 'LINEAR' fcq.keyframe_points[ -2].interpolation = 'LINEAR' fcq.keyframe_points[ -1].interpolation = 'LINEAR' fcq.keyframe_points[-4].co = fr, rot1[ax] fcq.keyframe_points[-3].co = f1, qua[ax] fcq.keyframe_points[-2].co = f2, qua[ax] fcq.keyframe_points[-1].co = fr3, rot2[ax] else: mat_loc.translation += amp * up_axis mat_bas = mdef[f].inverted() * matf * mat_loc if not use_local[f]: mat_bas.translation.rotate(mdef[f]) #loc, qua, _ = mat_bas.decompose() loc = mat_bas.translation # LOCATION UP for ax, fcl in enumerate(fc_loc[f]): fcl.keyframe_points.add(1) fcl.keyframe_points[ -1].interpolation = 'BEZIER' fcl.keyframe_points[ -1].handle_right_type = 'AUTO' fcl.keyframe_points[ -1].handle_left_type = 'AUTO' fcl.keyframe_points[-1].co = fr2, loc[ax] # ROTATION UP #for ax, fcq in enumerate(fc_qua[f]): # fcq.keyframe_points.add(1) # fcq.keyframe_points[-1].interpolation = 'LINEAR' # fcq.keyframe_points[-1].co = fr_up, qua[ax]''' is_global = set() for col_bone in awc.new_bones: name = col_bone.name if col_bone.seq_type == 'LR': if fr_f: lerp = .5 elif right: lerp = 0 else: lerp = 1 #cond = not fr_f #cond2 = right elif col_bone.seq_type == 'M': if not fr_f: lerp = .5 elif right: lerp = 1 else: lerp = 0 #cond = fr_f #cond2 = right else: #col_bone.seq_type == 'ES': if fr_f: lerp = 1 else: lerp = 0 #cond = True #cond2 = fr_f #if cond and name: if name: bone = rig.pose.bones[name] bone_dat = rig.data.bones[name] _loc = col_bone.loc1.lerp(col_bone.loc2, lerp) #if bone_dat.use_local_location: #_loc.rotate(mat) _rot = col_bone.qua1.slerp(col_bone.qua2, lerp) #if cond2: #_loc = col_bone.loc2 #_rot = col_bone.qua2 #else: #_loc = col_bone.loc1 #_rot = col_bone.qua1 if col_bone.add_torso and name not in is_global: is_global.add(name) #print(name, 'not is torso son') mat_loc = bone_dat.matrix_local.copy() mat_bas = Matrix.Translation( _loc) * _rot.to_matrix().to_4x4( ) # normalise rot ??? #mat_glo = mat*_ma_loc* _ma_bas if bone_dat.use_local_location: mat_bas = mat_loc.inverted( ) * mat * mat_loc * mat_bas else: mat_bas.translation.rotate(mat_loc) mat_bas = mat_loc.inverted( ) * mat * mat_loc * mat_bas mat_bas.translation.rotate(mat_loc) _loc, _rot, _ = mat_bas.decompose() for ax, fc in enumerate(f_curves[name][0]): keyp = fc.keyframe_points if keyp and keyp[-1].co.x == fr: fc.keyframe_points[-1].co.y += _loc[ ax] # !!!!!!!!!!!!!!!!!! else: fc.keyframe_points.add(1) fc.keyframe_points[-1].interpolation = 'BEZIER' fc.keyframe_points[-1].co = fr, _loc[ax] #fc.update() lrot = {} for ax, fc in enumerate(f_curves[name][1]): keyp = fc.keyframe_points if keyp and keyp[-1].co.x == fr: lrot[ax] = keyp[-1].co.y _rot_mode = bone.rotation_mode if _rot_mode == 'QUATERNION': lrot = Quaternion( (lrot[0] if 0 in lrot else 1, lrot[1] if 1 in lrot else 0, lrot[2] if 2 in lrot else 0, lrot[3] if 3 in lrot else 0)).normalized() _rot = lrot * _rot elif _rot_mode == 'AXIS_ANGLE': lrot = Quaternion( (lrot[1] if 1 in lrot else 0, lrot[2] if 2 in lrot else 1, lrot[3] if 3 in lrot else 0), lrot[0] if 0 in lrot else 0).normalized() _rot = lrot * _rot _rot = _rot.to_axis_angle() _rot = _rot[1], _rot[0][0], _rot[0][1], _rot[0][2] else: lrot = Euler((lrot[0] if 0 in lrot else 0, lrot[1] if 1 in lrot else 0, lrot[2] if 2 in lrot else 0), _rot_mode) _rot = lrot.to_quaternion() * _rot _rot = _rot.to_euler(_rot_mode) for ax, fc in enumerate(f_curves[name][1]): keyp = fc.keyframe_points if keyp and keyp[-1].co.x == fr: pass else: fc.keyframe_points.add(1) fc.keyframe_points[-1].interpolation = 'BEZIER' fc.keyframe_points[-1].co = fr, _rot[ax] for fc in fc_loc[0] + fc_loc[1]: fc.update() for fcl, fcr in f_curves.values(): for fc in fcl + fcr: fc.update() return {'FINISHED'} else: try: fc = rig.animation_data.action.fcurves except Exception as e: rig.animation_data.action = bpy.data.actions.new("rigAction") fc = rig.animation_data.action.fcurves l_foot_ik = rig.pose.bones[l_foot] r_foot_ik = rig.pose.bones[r_foot] dp_loc = 'pose.bones["%s"].location' % l_foot fc_lf = find_remove_keys(fc, dp_loc, 3, fr_start, fr_end) rot_modl = l_foot_ik.rotation_mode if rot_modl == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % l_foot size = 4 elif rot_modl == 'AXIS_ANGLE': dp_rot = 'pose.bones["%s"].rotation_axis_angle' % l_foot size = 4 else: dp_rot = 'pose.bones["%s"].rotation_euler' % l_foot size = 3 fcqua_lf = find_remove_keys(fc, dp_rot, size, fr_start, fr_end) dp_loc = 'pose.bones["%s"].location' % r_foot fc_rf = find_remove_keys(fc, dp_loc, 3, fr_start, fr_end) rot_modr = r_foot_ik.rotation_mode if rot_modr == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % r_foot size = 4 elif rot_modr == 'AXIS_ANGLE': dp_rot = 'pose.bones["%s"].rotation_axis_angle' % r_foot size = 4 else: dp_rot = 'pose.bones["%s"].rotation_euler' % r_foot size = 3 fcqua_rf = find_remove_keys(fc, dp_rot, size, fr_start, fr_end) del size, dp_loc, dp_rot lf_dat = rig.data.bones[l_foot] rf_dat = rig.data.bones[r_foot] #m_lo_lf = lf_dat.matrix_local.copy() #m_lo_rf = rf_dat.matrix_local.copy() mdef = lf_dat.matrix_local.copy(), rf_dat.matrix_local.copy() mmdef = lf_dat.matrix.copy(), rf_dat.matrix.copy() use_local = lf_dat.use_local_location, rf_dat.use_local_location fc_loc = fc_lf, fc_rf fc_qua = fcqua_lf, fcqua_rf rot_mode = rot_modl, rot_modr frec = awc.frequency up_axis = awc.up_axis.copy() up_axis.rotate(mtdat) side_axis = awc.side_axis.copy() side_axis.rotate(mtdat) front_axis = awc.front_axis.copy() front_axis.rotate(mtdat) openness = awc.openness amp = awc.amp #ant = 1 - awc.anticipation fo_rot = awc.foot_rot right = True ant = awc.anticipation - 1 dist = awc.step / 2 fr_start = awc.frame_start fr_end = awc.frame_end dif_fr = fr_end - fr_start cycles = int(dif_fr / frec) for c in range(cycles): f = c % 2 fr1 = c * frec fr2 = fr1 + frec / 2 fr3 = (c + 1) * frec fr4 = (c + 2) * frec s_axis = side_axis.copy() f_axis = front_axis.copy() u_axis = up_axis.copy() if use_local[f]: s_axis.rotate(mmdef[f]) f_axis.rotate(mmdef[f]) u_axis.rotate(mmdef[f]) op = (1 - 2 * f) * openness loc2 = ( (ant * dist * f_axis) + op * s_axis) * mmdef[f].inverted() loc1 = ((((2 * ant + 1) / 2) * dist * f_axis) + amp * u_axis) * mmdef[f].inverted() loc0 = (((1 + ant) * dist * f_axis) + op * s_axis) * mmdef[f].inverted() # LOCATION for ax, fcl in enumerate(fc_loc[f]): fcl.keyframe_points.add(4) fcl.keyframe_points[-4].interpolation = 'BEZIER' fcl.keyframe_points[-4].handle_right_type = 'VECTOR' fcl.keyframe_points[-4].handle_left_type = 'VECTOR' fcl.keyframe_points[-4].co = fr1, loc0[ax] fcl.keyframe_points[-3].interpolation = 'BEZIER' fcl.keyframe_points[-3].handle_right_type = 'AUTO' fcl.keyframe_points[-3].handle_left_type = 'AUTO' fcl.keyframe_points[-3].co = fr2, loc1[ax] fcl.keyframe_points[-2].interpolation = 'BEZIER' fcl.keyframe_points[-2].handle_right_type = 'VECTOR' fcl.keyframe_points[-2].handle_left_type = 'VECTOR' fcl.keyframe_points[-2].co = fr3, loc2[ax] fcl.keyframe_points[-1].interpolation = 'BEZIER' fcl.keyframe_points[-1].handle_right_type = 'VECTOR' fcl.keyframe_points[-1].handle_left_type = 'VECTOR' fcl.keyframe_points[-1].co = fr4, loc0[ax] #mod = fcl.modifiers.new('CYCLES') #mod.use_restricted_range = True #mod.frame_start = fr_start #mod.frame_end = fr_end # ROTATION #qua = mdef[f].to_quaternion() qua = Quaternion((1, 0, 0, 0)) axis = s_axis rot1 = Quaternion(axis, ant * fo_rot) rot2 = Quaternion(axis, (1 + ant) * fo_rot) f1 = fr4 - frec * (1 + ant / 2) f2 = fr4 - frec * (1 - (2 - ant) / 3) if rot_mode[f] == 'QUATERNION': pass elif rot_mode[f] == 'AXIS_ANGLE': qua = qua.to_axis_angle() qua = qua[1], qua[0][0], qua[0][1], qua[0][2] rot1 = rot1.to_axis_angle() rot1 = rot1[1], rot1[0][0], rot1[0][1], rot1[0][2] rot2 = rot2.to_axis_angle() rot2 = rot2[1], rot2[0][0], rot2[0][1], rot2[0][2] else: qua = qua.to_euler(rot_mode[f]) rot1 = rot1.to_euler(rot_mode[f], qua) rot2 = rot2.to_euler(rot_mode[f], qua) for ax, fcq in enumerate(fc_qua[f]): fcq.keyframe_points.add(4) fcq.keyframe_points[-4].interpolation = 'LINEAR' fcq.keyframe_points[-3].interpolation = 'LINEAR' fcq.keyframe_points[-2].interpolation = 'LINEAR' fcq.keyframe_points[-1].interpolation = 'LINEAR' fcq.keyframe_points[-4].co = fr3, rot1[ax] fcq.keyframe_points[-3].co = f1, qua[ax] fcq.keyframe_points[-2].co = f2, qua[ax] fcq.keyframe_points[-1].co = fr4, rot2[ax] f_curves = {} for col_bone in awc.new_bones: name = col_bone.name if name: loc1 = col_bone.loc1.copy() loc2 = col_bone.loc2.copy() qua1 = col_bone.qua1.copy() qua2 = col_bone.qua2.copy() if name not in f_curves: f_curves[name] = {} if col_bone.seq_type == 'ES': if fr1 in f_curves[name]: f_curves[name][fr1][0] += loc1 f_curves[name][fr1][1] *= qua1 else: f_curves[name][fr1] = [loc1, qua1] if fr2 in f_curves[name]: f_curves[name][fr2][0] += loc2 f_curves[name][fr2][1] *= qua2 else: f_curves[name][fr2] = [loc2, qua2] elif col_bone.seq_type == 'LR': if fr1 in f_curves[name]: f_curves[name][fr1][0] += loc1 if f else loc2 f_curves[name][fr1][1] *= qua1 if f else qua2 else: f_curves[name][fr1] = [ loc1 if f else loc2, qua1 if f else qua2 ] if fr2 in f_curves[name]: f_curves[name][fr2][0] += loc1.lerp(loc2, .5) f_curves[name][fr2][1] *= qua1.slerp(qua2, .5) else: f_curves[name][fr2] = [ loc1.lerp(loc2, .5), qua1.slerp(qua2, .5) ] elif col_bone.seq_type == 'M': if fr1 in f_curves[name]: f_curves[name][fr1][0] += loc1.lerp(loc2, .5) f_curves[name][fr1][1] *= qua1.slerp(qua2, .5) else: f_curves[name][fr1] = [ loc1.lerp(loc2, .5), qua1.slerp(qua2, .5) ] if fr2 in f_curves[name]: f_curves[name][fr2][0] += loc1 if f else loc2 f_curves[name][fr2][1] *= qua1 if f else qua2 else: f_curves[name][fr2] = [ loc1 if f else loc2, qua1 if f else qua2 ] for name in f_curves: bone = rig.pose.bones[col_bone.name] _rot_mode = bone.rotation_mode dp_loc = 'pose.bones["%s"].location' % name for fr in f_curves[name]: loc, rot = f_curves[name][fr] if _rot_mode == 'QUATERNION': dp_rot = 'pose.bones["%s"].rotation_quaternion' % name size = 4 elif _rot_mode == 'AXIS_ANGLE': rot = rot.to_axis_angle() rot = rot1[1], rot1[0][0], rot1[0][1], rot1[0][2] dp_rot = 'pose.bones["%s"].rotation_axis_angle' % name size = 4 else: rot = rot.to_euler(_rot_mode, qua) dp_rot = 'pose.bones["%s"].rotation_euler' % name size = 3 # LOCATION for i in range(3): fcl = fc.find(dp_loc, index=i) if not fcl: fcl = fc.new(data_path=dp_loc, index=i) fcl.keyframe_points.add(1) fcl.keyframe_points[-1].interpolation = 'BEZIER' fcl.keyframe_points[-1].handle_right_type = 'AUTO' fcl.keyframe_points[-1].handle_left_type = 'AUTO' fcl.keyframe_points[-1].co = fr, loc[i] fcl.update() # ROTATION for i in range(size): fcr = fc.find(dp_rot, index=i) if not fcr: fcr = fc.new(data_path=dp_rot, index=i) fcr.keyframe_points.add(1) fcr.keyframe_points[-1].interpolation = 'BEZIER' fcr.keyframe_points[-1].handle_right_type = 'AUTO' fcr.keyframe_points[-1].handle_left_type = 'AUTO' fcr.keyframe_points[-1].co = fr, rot[i] fcr.update() #print('not suported') for fc in fc_loc[0] + fc_loc[1] + fc_qua[0] + fc_qua[1]: fc.update() return {'FINISHED'}
def load(context, filepath): csvpath = filepath.replace('.obj', '_ModelPlacementInformation.csv') bpy.ops.import_scene.obj(filepath=filepath) # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[ mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) # Select the imported WMO obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: obj.rotation_euler = [0, 0, 0] obj.rotation_euler.x += radians(90) obj.rotation_euler.z -= radians(90) # Read doodad definitions file with open(csvpath) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: doodad_path, doodad_filename = os.path.split(filepath) newpath = os.path.join(doodad_path, row['ModelFile']) # Import the doodad bpy.ops.import_scene.obj(filepath=newpath) # Select the imported doodad obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: # Print object name # print (obj.name) # Prepend name obj.name = "(" + row['DoodadSet'] + ") " + obj.name # Set position obj.location = (float(row['PositionY']) * -1, float(row['PositionX']), float(row['PositionZ'])) # Set rotation rotQuat = Quaternion( (float(row['RotationW']), float(row['RotationX']), float(row['RotationY']), float(row['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90) rotEul.z += radians(90) obj.rotation_euler = rotEul # Set scale if row['ScaleFactor']: obj.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[ mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) return {'FINISHED'}
def load(context, filepath ): with ProgressReport(context.window_manager) as progress: progress.enter_substeps(1, "Importing WMO OBJ %r..." % filepath) csvpath = filepath.replace('.obj', '_ModelPlacementInformation.csv') bpy.ops.import_scene.obj(filepath=filepath) # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) # Select the imported WMO obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: obj.rotation_euler = [0, 0, 0] obj.rotation_euler.x += radians(90) obj.rotation_euler.z -= radians(90) # Read doodad definitions file with open(csvpath) as csvfile: reader = csv.DictReader(csvfile, delimiter=';') for row in reader: doodad_path, doodad_filename = os.path.split(filepath) newpath = os.path.join(doodad_path, row['ModelFile']) # Import the doodad bpy.ops.import_scene.obj(filepath=newpath) # Select the imported doodad obj_objects = bpy.context.selected_objects[:] for obj in obj_objects: # Print object name # print (obj.name) # Prepend name obj.name = "(" + row['DoodadSet'] + ") " + obj.name # Set position obj.location = (float(row['PositionY']) * -1, float(row['PositionX']), float(row['PositionZ'])) # Set rotation rotQuat = Quaternion((float(row['RotationW']), float(row['RotationX']), float(row['RotationY']), float(row['RotationZ']))) rotEul = rotQuat.to_euler() rotEul.x += radians(90); rotEul.z += radians(90); obj.rotation_euler = rotEul # Set scale if row['ScaleFactor']: obj.scale = (float(row['ScaleFactor']), float(row['ScaleFactor']), float(row['ScaleFactor'])) # Duplicate material removal script by Kruithne # Merge all duplicate materials for obj in bpy.context.scene.objects: if obj.type == 'MESH': i = 0 for mat_slot in obj.material_slots: mat = mat_slot.material obj.material_slots[i].material = bpy.data.materials[mat.name.split('.')[0]] i += 1 # Cleanup unused materials for img in bpy.data.images: if not img.users: bpy.data.images.remove(img) progress.leave_substeps("Finished importing: %r" % filepath) return {'FINISHED'}