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()
Beispiel #2
0
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
Beispiel #3
0
 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')
Beispiel #4
0
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
Beispiel #5
0
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
Beispiel #6
0
 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)
Beispiel #8
0
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
Beispiel #9
0
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)
Beispiel #10
0
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
Beispiel #11
0
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... ... -.-")
Beispiel #14
0
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
Beispiel #15
0
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 _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
Beispiel #18
0
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()
Beispiel #19
0
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)
Beispiel #20
0
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)) 
Beispiel #21
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)
Beispiel #22
0
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))
Beispiel #24
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
Beispiel #25
0
        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'}
Beispiel #28
0
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
Beispiel #29
0
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'}
Beispiel #31
0
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'}