def export_arms_fix(exportfolderpath, bodyNo):
    #
    # first we need to start with arm_LClips1__arm_L_initSource
    # but this is not done yet, how could I miss this initialization?
    # on a second thought, to match the body, maybe this should be actually 0 ? game default has a rotation on Y axis of -18/18 degrees
    #
    neck_joint01 = bpy.data.objects["_neck_joint01"]
    wrist_L_joint = bpy.data.objects["_wrist_L_joint"]
    forearm_L_joint = bpy.data.objects["_forearm_L_joint"]
    forearm_L_joint = bpy.data.objects["_forearm_L_joint"]
    arm_R_ikEffector, arm_R_ikHandle = getIKValues("Armature", "elbow_joint.R",
                                                   "wrist_joint.R")
    arm_R_ikEffector, arm_R_ikHandle, distance, translation = getClosestPointFromBoneProjection(
        "Armature", "elbow_joint.R", "wrist_joint.R")
    arm_L_ikEffector, arm_L_ikHandle, distance, translation = getClosestPointFromBoneProjection(
        "Armature", "elbow_joint.L", "wrist_joint.L")
    arms_fix_string = "\n"
    #
    #arm_LClips1__arm_L_initSource
    #those are actually rotations that are applied to the hands, in this case we want to keep the rest pose at 0
    snippet = "var :mySplineVector3f :Person\" + :person + \"Anim:Model01:arm_LClips1__arm_L_initSource.Curve[0] ?;"
    mySplineVectorString = "(" + " {:.6g}f,".format(0) + " {:.6g}f,".format(
        0) + " {:.6g}f".format(0) + " )"
    snippet = snippet + "\n:mySplineVector3f.KeyValue [ " + mySplineVectorString + " , " + mySplineVectorString + " ];"
    snippet = snippet + "\ndel :mySplineVector3f;"
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #arm_RClips1__arm_R_initSource1   (there must be a 1 at the end, is not like arm_RClips1__arm_R_initSource and that is it)
    snippet = "var :mySplineVector3f :Person\" + :person + \"Anim:Model01:arm_RClips1__arm_R_initSource1.Curve[0] ?;"
    mySplineVectorString = "(" + " {:.6g}f,".format(0) + " {:.6g}f,".format(
        0) + " {:.6g}f".format(0) + " )"
    snippet = snippet + "\n:mySplineVector3f.KeyValue [ " + mySplineVectorString + " , " + mySplineVectorString + " ];"
    snippet = snippet + "\ndel :mySplineVector3f;"
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #
    ob = bpy.data.objects.new("_neck_joint01_translated", None)
    ob.rotation_mode = 'YZX'
    ob.parent = neck_joint01
    ob.matrix_world = neck_joint01.matrix_world
    ob.matrix_basis = ob.matrix_parent_inverse * ob.matrix_basis
    ob.matrix_parent_inverse.identity()
    # Define the translation we want to perform in local space (after rotation) # we actually move down the local Y axis of the ankle joint
    trans_local = neck_joint01.matrix_world.inverted() * Vector((0, 0, 0))
    # Convert the local translation to global with the 3x3 rotation matrix of our object
    trans_world = ob.matrix_world.to_3x3() * trans_local
    # Apply the translation
    ob.matrix_world.translation += trans_world
    bpy.context.scene.objects.link(ob)
    neck_joint01_translated = ob
    #
    #elbow_LClips1__elbow_L_initSource + elbow_RClips1__elbow_R_initSource
    elbow_initSource = neck_joint01.matrix_world.inverted() * Vector((0, 0, 0))
    snippet = "var :mySplineVector3f :Person\" + :person + \"Anim:Model01:elbow_LClips1__elbow_L_initSource.Curve[0] ?;"
    mySplineVectorString = "(" + " {:.6g}f,".format(
        elbow_initSource.y +
        0) + " {:.6g}f,".format(-elbow_initSource.z +
                                0) + " {:.6g}f".format(elbow_initSource.x +
                                                       0) + " )"  #??? y,-z,x
    snippet = snippet + "\n:mySplineVector3f.KeyValue [ " + mySplineVectorString + " , " + mySplineVectorString + " ];"
    snippet = snippet + "\ndel :mySplineVector3f;"
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    snippet = "var :mySplineVector3f :Person\" + :person + \"Anim:Model01:elbow_RClips1__elbow_R_initSource.Curve[0] ?;"
    mySplineVectorString = "(" + " {:.6g}f,".format(
        elbow_initSource.y +
        0) + " {:.6g}f,".format(-elbow_initSource.z +
                                0) + " {:.6g}f".format(elbow_initSource.x +
                                                       0) + " )"  # y,-z,x
    snippet = snippet + "\n:mySplineVector3f.KeyValue [ " + mySplineVectorString + " , " + mySplineVectorString + " ];"
    snippet = snippet + "\ndel :mySplineVector3f;"
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #effector
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_L_effector"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.ScalingPivot (" + " {:.6f}f,".format(
        wrist_L_joint.location.y + 0) + " {:.6f}f,".format(
            wrist_L_joint.location.x + 0) + " {:.6f}f".format(
                wrist_L_joint.location.z +
                0) + " );\n"  #here we switch  from yzx to yxz
    snippet = snippet + "\t.RotationPivot (" + " {:.6f}f,".format(
        wrist_L_joint.location.y + 0) + " {:.6f}f,".format(
            wrist_L_joint.location.x + 0) + " {:.6f}f".format(
                wrist_L_joint.location.z +
                0) + " );\n"  #here we switch  from yzx to yxz
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        forearm_L_joint.location.y + 0) + " {:.6f}f,".format(
            forearm_L_joint.location.z +
            0) + " {:.6f}f".format(forearm_L_joint.location.x +
                                   0) + " );\n"  #no switch
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #hand_L_target01
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "hand_L_target01"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.ScalingPivot (" + " {:.6f}f,".format(
        arm_L_ikHandle.x +
        0) + " {:.6f}f,".format(arm_L_ikHandle.z + 0) + " {:.6g}f".format(
            -arm_L_ikHandle.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "\t.RotationPivot (" + " {:.6f}f,".format(
        arm_L_ikHandle.x +
        0) + " {:.6f}f,".format(arm_L_ikHandle.z + 0) + " {:.6g}f".format(
            -arm_L_ikHandle.y + 0) + " );\n"  #here we switch to xz -y
    #old code below
    #snippet = snippet+ "\t.ScalingPivot ("        +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().z+ 0)    +" {:.6g}f".format(-wrist_L_joint.matrix_world.to_translation().y+ 0)   +" );\n"   #here we switch to xz -y
    #snippet = snippet+ "\t.RotationPivot ("        +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().z+ 0)    +" {:.6g}f".format(-wrist_L_joint.matrix_world.to_translation().y+ 0)   +" );\n"   #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #arm_L_group depends on hand_L_target01_locator_parent because it has a constraint reparent on it
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "hand_L_target01_locator_parent"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        arm_L_ikHandle.x +
        0) + " {:.6f}f,".format(arm_L_ikHandle.z +
                                0) + " {:.6f}f".format(-arm_L_ikHandle.y +
                                                       0) + " );\n"  #no switch
    #snippet = snippet+ "\t.Translation ("        +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_L_joint.matrix_world.to_translation().z+ 0)    +" {:.6f}f".format(-wrist_L_joint.matrix_world.to_translation().y+ 0)   +" );\n"  #no switch
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #arm_L_locator
    #
    fingers_average_location = Vector((0, 0, 0))
    fingers_names = [
        "_finger01_L_joint01", "_finger02_L_joint01", "_finger03_L_joint01",
        "_finger04_L_joint01", "_finger05_L_joint01", "_finger01_L_joint02",
        "_finger02_L_joint02", "_finger03_L_joint02", "_finger04_L_joint02",
        "_finger05_L_joint02"
    ]
    for finger in fingers_names:
        fingers_average_location += bpy.data.objects[
            finger].matrix_world.translation

    fingers_average_location = fingers_average_location / len(fingers_names)
    difference = fingers_average_location - arm_L_ikHandle  #wrist_L_joint.matrix_world.to_translation()
    #
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_L_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        difference.x +
        0) + " {:.6f}f,".format(difference.z + 0) + " {:.6g}f".format(
            -difference.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "\t.Rotation ( 0f, 180f, 0f );\n"
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    # arm_L_base_locator
    # I think arm_R_offset_locator moves in the center of palm, then it rotates then returns back to wrist loc
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_L_base_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        -difference.x +
        0) + " {:.6f}f,".format(-difference.z + 0) + " {:.6g}f".format(
            difference.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #arm_L_ikHandle
    # this should be maybe all zero ?!??
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_L_ikHandle"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        0) + " {:.6f}f,".format(0) + " {:.6g}f".format(0) + " );\n"
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    snippet = ":Person\" + :person + \"Pick:body_hand_L_pick.SNode?.Translation ( -0.096892565f, 0.0010810591f, -0.0056944136f );\n"
    #:Person" + :person + "Pick:body_hand_L_pick.SNode?.Translation ( -0.096892565f, 0.0010810591f, -0.0056944136f );
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #Selbow_L_group
    line_b = bpy.data.objects["_elbow_L_joint"].matrix_world.to_translation()
    # we move it along local Y axis, get the moved vector then move it back to original location
    bpy.data.objects["_elbow_L_joint"].matrix_basis *= Matrix.Translation(
        (0.0, -1.0, 0.0))
    #for some reason we need to update the scene, otherwise the matrix wont work
    bpy.data.scenes[0].update()
    line_a = bpy.data.objects["_elbow_L_joint"].matrix_world.to_translation()
    bpy.data.objects["_elbow_L_joint"].matrix_basis *= Matrix.Translation(
        (0.0, 1.0, 0.0))
    bpy.data.scenes[0].update()
    #
    plane_co = bpy.data.objects[
        "_shoulder_L_joint"].matrix_world.to_translation()
    plane_no = Vector((-1, 0, 0))
    calculated_elbow_L_group_world_coordinates = mathutils.geometry.intersect_line_plane(
        line_a, line_b, plane_co, plane_no)
    #new code, now we calculate elbow manipulator based on empty _arm_pole_L
    calculated_elbow_L_group_world_coordinates = bpy.data.objects[
        "_arm_pole_L"].matrix_world.to_translation()
    calculated_elbow_L_group_local_coord = neck_joint01_translated.matrix_world.inverted(
    ) * calculated_elbow_L_group_world_coordinates
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "elbow_L_group"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.RotationPivot (" + " {:.6f}f,".format(
        calculated_elbow_L_group_local_coord.y + 0
    ) + " {:.6f}f,".format(
        calculated_elbow_L_group_local_coord.z + 0
    ) + " {:.6f}f".format(
        calculated_elbow_L_group_local_coord.x + 0
    ) + " );\n"  #here we switch to yzx because we are parented to neck joint
    #we also need to do RotationPivotTranslation ...
    #but if we calculated above correctly, then there should be no requirements for RotationPivotTranslation, as this was a bug in original game (location was in world coordinates and they had to fix that back to local)
    snippet = snippet + "\t.RotationPivotTranslation (" + " {:.6f}f,".format(
        0) + " {:.6f}f,".format(0) + " {:.6g}f".format(
            0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #ellbow_L_locator
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "ellbow_L_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        calculated_elbow_L_group_local_coord.y + 0
    ) + " {:.6f}f,".format(
        calculated_elbow_L_group_local_coord.z + 0
    ) + " {:.6f}f".format(
        calculated_elbow_L_group_local_coord.x + 0
    ) + " );\n"  #here we switch to yzx because we are parented to neck joint
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #
    #
    wrist_R_joint = bpy.data.objects["_wrist_R_joint"]
    forearm_R_joint = bpy.data.objects["_forearm_R_joint"]
    elbow_R_joint = bpy.data.objects["_elbow_R_joint"]
    arm_R_ikEffector, arm_R_ikHandle = getIKValues("Armature", "elbow_joint.R",
                                                   "wrist_joint.R")
    arm_R_ikEffector, arm_R_ikHandle, distance, translationAlongY = getClosestPointFromBoneProjection(
        "Armature", "elbow_joint.R", "wrist_joint.R")
    localCo, worldCo, distance, translationAlongY = getClosestPointFromBoneProjection(
        "Armature", "forearm_joint.R", "wrist_joint.R")
    wrist_R_joint_world_coordinates = wrist_R_joint.matrix_world.to_translation(
    )
    arm_effector = elbow_R_joint.matrix_world.inverted(
    ) * wrist_R_joint_world_coordinates
    #
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_R_effector"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.ScalingPivot (" + " {:.6g}f,".format(
        translationAlongY.x +
        0) + " {:.6g}f,".format(translationAlongY.y +
                                0) + " {:.6g}f".format(translationAlongY.z +
                                                       0) + " );\n"  #no switch
    snippet = snippet + "\t.RotationPivot (" + " {:.6g}f,".format(
        translationAlongY.x +
        0) + " {:.6g}f,".format(translationAlongY.y +
                                0) + " {:.6g}f".format(translationAlongY.z +
                                                       0) + " );\n"  #no switch
    #snippet = snippet+ "\t.RotationPivot ("        +" {:.6g}f,".format(arm_R_ikEffector.x - forearm_R_joint.location.y+ 0)    +" {:.6g}f,".format(arm_R_ikEffector.y - forearm_R_joint.location.z+ 0)    +" {:.6g}f".format(arm_R_ikEffector.z - forearm_R_joint.location.x + 0)   +" );\n"  #no switch
    #snippet = snippet+ "\t.ScalingPivot ("        +" {:.6g}f,".format(arm_R_ikEffector.x - forearm_R_joint.location.y+ 0)    +" {:.6g}f,".format(arm_R_ikEffector.y - forearm_R_joint.location.z+ 0)    +" {:.6g}f".format(arm_R_ikEffector.z - forearm_R_joint.location.x + 0)   +" );\n"  #no switch
    #snippet = snippet+ "\t.ScalingPivot ("        +" {:.6f}f,".format(arm_effector.y - forearm_R_joint.location.y + 0)    +" {:.6f}f,".format(arm_effector.z - forearm_R_joint.location.z+ 0)    +" {:.6g}f".format(arm_effector.x - forearm_R_joint.location.x+ 0)   +" );\n"   #here we switch  from yzx to yxz
    #snippet = snippet+ "\t.ScalingPivot ("        +" {:.6f}f,".format(wrist_R_joint.location.y+ 0)    +" {:.6f}f,".format(wrist_R_joint.location.x+ 0)    +" {:.6g}f".format(wrist_R_joint.location.z+ 0)   +" );\n"   #here we switch  from yzx to yxz
    #snippet = snippet+ "\t.RotationPivot ("        +" {:.6f}f,".format(wrist_R_joint.location.y+ 0)    +" {:.6f}f,".format(wrist_R_joint.location.x+ 0)    +" {:.6g}f".format(wrist_R_joint.location.z+ 0)   +" );\n"  #here we switch  from yzx to yxz
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        forearm_R_joint.location.y + 0) + " {:.6f}f,".format(
            forearm_R_joint.location.z +
            0) + " {:.6g}f".format(forearm_R_joint.location.x +
                                   0) + " );\n"  #no switch
    #snippet = snippet+ "\t.Translation ("        +" {:.6f}f,".format(arm_effector.x+ 0)    +" {:.6f}f,".format(arm_effector.z+ 0)    +" {:.6g}f".format(-arm_effector.y+ 0)   +" );\n"  #no switch
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #arm_R_group depends on hand_R_target01_locator_parent because it has a constraint reparent on it
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "hand_R_target01_locator_parent"
    snippet = snippet + ".SNode? . {\n"
    #snippet = snippet+ "\t.Translation ("        +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().z+ 0)    +" {:.6g}f".format(-wrist_R_joint.matrix_world.to_translation().y+ 0)   +" );\n"  #here we switch to xz -y	(daz to villa)
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        arm_R_ikHandle.x +
        0) + " {:.6f}f,".format(arm_R_ikHandle.z +
                                0) + " {:.6f}f".format(-arm_R_ikHandle.y +
                                                       0) + " );\n"  #no switch
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "hand_R_target01"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.ScalingPivot (" + " {:.6f}f,".format(
        arm_R_ikHandle.x +
        0) + " {:.6f}f,".format(arm_R_ikHandle.z + 0) + " {:.6g}f".format(
            -arm_R_ikHandle.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "\t.RotationPivot (" + " {:.6f}f,".format(
        arm_R_ikHandle.x +
        0) + " {:.6f}f,".format(arm_R_ikHandle.z + 0) + " {:.6g}f".format(
            -arm_R_ikHandle.y + 0) + " );\n"  #here we switch to xz -y
    #snippet = snippet+ "\t.ScalingPivot ("        +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().z+ 0)    +" {:.6g}f".format(-wrist_R_joint.matrix_world.to_translation().y+ 0)   +" );\n"   #here we switch to xz -y
    #snippet = snippet+ "\t.RotationPivot ("        +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().x+ 0)    +" {:.6f}f,".format(wrist_R_joint.matrix_world.to_translation().z+ 0)    +" {:.6g}f".format(-wrist_R_joint.matrix_world.to_translation().y+ 0)   +" );\n"   #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #arm_R_locator
    #
    fingers_average_location = Vector((0, 0, 0))
    fingers_names = [
        "_finger01_R_joint01", "_finger02_R_joint01", "_finger03_R_joint01",
        "_finger04_R_joint01", "_finger05_R_joint01", "_finger01_R_joint02",
        "_finger02_R_joint02", "_finger03_R_joint02", "_finger04_R_joint02",
        "_finger05_R_joint02"
    ]
    for finger in fingers_names:
        fingers_average_location += bpy.data.objects[
            finger].matrix_world.translation

    fingers_average_location = fingers_average_location / len(fingers_names)
    difference = fingers_average_location - wrist_R_joint.matrix_world.to_translation(
    )
    #
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_R_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        difference.x +
        0) + " {:.6f}f,".format(difference.z + 0) + " {:.6g}f".format(
            -difference.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    # arm_R_base_locator
    # I think arm_R_offset_locator moves in the center of palm, then it rotates then returns back to wrist loc
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_R_base_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        -difference.x +
        0) + " {:.6f}f,".format(-difference.z + 0) + " {:.6g}f".format(
            difference.y + 0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "\t.Rotation ( 0f, 0f, 180f );\n"
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #wrist_R_joint_orientConstraint1.OrientOffset
    wrist_fake_joint_R = bpy.data.objects["_wrist_fake_joint_R"]
    snippet = ":Person\" + :person + \"Anim:Model01:wrist_R_joint_orientConstraint1.OrientOffset (" + " {:.6f}f,".format(
        degrees(wrist_fake_joint_R.rotation_euler.y) + 0) + " {:.6f}f,".format(
            degrees(wrist_fake_joint_R.rotation_euler.z) +
            0) + " {:.6g}f".format(
                degrees(wrist_fake_joint_R.rotation_euler.x) +
                0) + " );\n"  #here we switch to y z x
    snippet = snippet + "\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #arm_R_ikHandle
    # this should be maybe all zero ?!??
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "arm_R_ikHandle"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        0) + " {:.6f}f,".format(0) + " {:.6g}f".format(0) + " );\n"
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #
    #Selbow_R_group
    line_b = bpy.data.objects["_elbow_R_joint"].matrix_world.to_translation()
    # we move it along local Y axis, get the moved vector then move it back to original location
    bpy.data.objects["_elbow_R_joint"].matrix_basis *= Matrix.Translation(
        (0.0, 1.0, 0.0))
    #for some reason we need to update the scene, otherwise the matrix wont work
    bpy.data.scenes[0].update()
    line_a = bpy.data.objects["_elbow_R_joint"].matrix_world.to_translation()
    bpy.data.objects["_elbow_R_joint"].matrix_basis *= Matrix.Translation(
        (0.0, -1.0, 0.0))
    bpy.data.scenes[0].update()
    #
    plane_co = bpy.data.objects[
        "_shoulder_R_joint"].matrix_world.to_translation()
    plane_no = Vector((-1, 0, 0))
    calculated_elbow_R_group_world_coordinates = mathutils.geometry.intersect_line_plane(
        line_a, line_b, plane_co, plane_no)
    ##=new code, now we calculate elbow manipulator based on empty _arm_pole_R
    calculated_elbow_R_group_world_coordinates = bpy.data.objects[
        "_arm_pole_R"].matrix_world.to_translation()
    calculated_elbow_R_group_local_coord = neck_joint01_translated.matrix_world.inverted(
    ) * calculated_elbow_R_group_world_coordinates
    #bpy.context.scene.cursor_location = neck_joint01_translated.matrix_world * calculated_elbow_R_group_local_coord
    #
    #neck_joint01_matrix = neck_joint01.matrix_local.copy()
    #mat_loc = mathutils.Matrix.Translation(calculated_elbow_R_group_local_coord)
    #mat_rot = neck_joint01_matrix.to_3x3()
    #new_mat = mat_loc * mat_rot
    #direction = elbow_initSource.copy()
    #direction.rotate(neck_joint01.matrix_world)
    #custom_location = neck_joint01.location + direction
    #
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "elbow_R_group"
    snippet = snippet + ".SNode? . {\n"
    #	.RotationPivot ( 1.412567f, -0.148455f, 0.331618f );
    snippet = snippet + "\t.RotationPivot (" + " {:.6f}f,".format(
        calculated_elbow_R_group_local_coord.y + 0) + " {:.6f}f,".format(
            calculated_elbow_R_group_local_coord.z +
            0) + " {:.6f}f".format(calculated_elbow_R_group_local_coord.x +
                                   0) + " );\n"  #here we switch to xz -y
    #we also need to do RotationPivotTranslation ...
    #but if we calculated above correctly, then there should be no requirements for RotationPivotTranslation
    snippet = snippet + "\t.RotationPivotTranslation (" + " {:.6f}f,".format(
        0) + " {:.6f}f,".format(0) + " {:.6f}f".format(
            0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    #ellbow_R_locator
    snippet = ":Person\" + :person + \"Anim:Model01:"
    snippet = snippet + "ellbow_R_locator"
    snippet = snippet + ".SNode? . {\n"
    snippet = snippet + "\t.Translation (" + " {:.6f}f,".format(
        calculated_elbow_R_group_local_coord.y + 0) + " {:.6f}f,".format(
            calculated_elbow_R_group_local_coord.z +
            0) + " {:.6f}f".format(calculated_elbow_R_group_local_coord.x +
                                   0) + " );\n"  #here we switch to xz -y
    snippet = snippet + "};\n"
    snippet = snippet + ""
    arms_fix_string = arms_fix_string + snippet
    arms_fix_string = arms_fix_string + "\n"
    #
    arms_fix_string += ":Person\" + :person + \"Anim:Model01:wrist_L_joint.SNode?.RotationAxis (0f, 0f, 0f);\n"
    print(arms_fix_string)
    file_path = exportfolderpath + "AcBody" + bodyNo + "Collision.bs"
    f = open(file_path, 'a')
    f.write(arms_fix_string)
    f.flush()
    f.close()
Esempio n. 2
0
def objects_to_bmesh(objs, transform=True):
    """ Merges multiple objects into one bmesh for export """

    # CAUTION: Removes/destroys custom layer props

    # Creates the mesh used to merge the entire scene
    bm_all = bmesh.new()

    # Adds the objects" meshes to the bmesh
    for obj in objs:
        dprint("Preparing object {} for export...".format(obj.name))
        # Creates a bmesh from the supplied object
        bm = bmesh.new()
        bm.from_mesh(obj.data)

        # Makes sure all layers exist so values don't get lost while exporting
        uv_layer = bm.loops.layers.uv.get("UVMap")
        tex_layer = bm.faces.layers.tex.get("UVMap")
        vc_layer = (bm.loops.layers.color.get("Col")
                    or bm.loops.layers.color.new("Col"))
        env_layer = (bm.loops.layers.color.get("Env")
                     or bm.loops.layers.color.new("Env"))
        env_alpha_layer = (bm.faces.layers.float.get("EnvAlpha")
                           or bm.faces.layers.float.new("EnvAlpha"))
        va_layer = (bm.loops.layers.color.get("Alpha")
                    or bm.loops.layers.color.new("Alpha"))
        texnum_layer = bm.faces.layers.int.get("Texture Number")
        type_layer = (bm.faces.layers.int.get("Type")
                      or bm.faces.layers.int.new("Type"))
        material_layer = (bm.faces.layers.int.get("Material")
                          or bm.faces.layers.int.new("Material"))

        # Removes the parent for exporting and applies transformation
        parent = obj.parent
        if parent:
            mat = obj.matrix_world.copy()
            old_mat = obj.matrix_basis.copy()
            obj.parent = None
            obj.matrix_world = mat

        spc = obj.matrix_basis
        bmesh.ops.scale(bm, vec=obj.scale, space=spc, verts=bm.verts)
        if transform:
            bmesh.ops.transform(bm,
                                matrix=Matrix.Translation(obj.location),
                                space=spc,
                                verts=bm.verts)
        bmesh.ops.rotate(bm,
                         cent=obj.location,
                         matrix=obj.rotation_euler.to_matrix(),
                         space=spc,
                         verts=bm.verts)

        # Restores the parent relationship
        if parent and not obj.parent:
            obj.parent = parent
            obj.matrix_basis = old_mat

        # Converts the transformed bmesh to mesh
        new_mesh = bpy.data.meshes.new("ncp_export_temp")
        bm.to_mesh(new_mesh)

        # Adds the transformed mesh to the big bmesh
        bm_all.from_mesh(new_mesh)

        # Removes unused meshes
        bpy.data.meshes.remove(new_mesh, do_unlink=True)
        bm.free()

    return bm_all
Esempio n. 3
0
 def action_common(self, context, redoing) :
     try :
         curve_name = "Curlicue"
         vertices = []
         faces = []
         for i in range(self.nr_points) :
             angle = i / self.nr_points * self.nr_turns * 2 * math.pi
             if self.curve_type == "linear" :
                 radius = \
                     (
                         i / self.nr_points * (self.radius - self.linear_offset)
                     +
                         self.linear_offset
                     )
             elif self.curve_type == "log" :
                 radius = \
                     (
                         self.radius
                     *
                         self.radius_ratio ** (angle / (2 * math.pi) - self.nr_turns)
                     )
             else :
                 raise Failure("SHOULDN’T OCCUR: unrecognized curve type")
             #end if
             width = \
                 (
                     self.outer_taper * i / self.nr_points
                 +
                     self.inner_taper * (1 - i / self.nr_points)
                 )
             to_midpoint = \
                 (
                     Matrix.Rotation(angle, 4, "Z")
                 *
                     Matrix.Translation(Vector((radius, 0, 0)))
                 )
             orient = math.pi / 2 # !
             pt1 = \
                 (
                     to_midpoint
                 *
                     Matrix.Rotation(orient + math.pi / 2, 4, "Z")
                 *
                     Matrix.Translation(Vector((width / 2, 0, 0)))
                 *
                     Vector((0, 0, 0))
                 )
             pt2 = \
                 (
                     to_midpoint
                 *
                     Matrix.Rotation(orient - math.pi / 2, 4, "Z")
                 *
                     Matrix.Translation(Vector((width / 2, 0, 0)))
                 *
                     Vector((0, 0, 0))
                 )
             vertices.extend([pt1, pt2])
             if len(vertices) >= 4 :
                 faces.append(list(len(vertices) + i for i in (-4, -3, -1, -2)))
             #end if
         #end for
         the_curve = bpy.data.meshes.new(curve_name)
         the_curve.from_pydata(vertices, [], faces)
         object_utils.object_data_add(context, the_curve, name = curve_name)
         # all done
         status = {"FINISHED"}
     except Failure as why :
         sys.stderr.write("Failure: {}\n".format(why.msg)) # debug
         self.report({"ERROR"}, why.msg)
         status = {"CANCELLED"}
     #end try
     return \
         status
Esempio n. 4
0
 def view_matrix(self):
     return Matrix.Translation(Vector((0, 0, 5)))
Esempio n. 5
0
import bpy
from mathutils import Vector, Matrix
import math
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
x, y, z = 0, 0, 0
for i in range(10):
    bpy.ops.mesh.primitive_cube_add(location=[x, y, z])
    obj = bpy.context.active_object
    translation = (0, 0, 2 * i)
    translation_matrix = Matrix.Translation(translation)
    print("Translation matrix ", translation_matrix)
    obj.matrix_world *= translation_matrix
Esempio n. 6
0
def loc_mat(mat):
    return Matrix.Translation(mat.to_translation()).to_4x4()
    def set_bone_transforms(gltf, skin_id, bone, node_id, parent):

        pyskin = gltf.data.skins[skin_id]
        pynode = gltf.data.nodes[node_id]

        obj = bpy.data.objects[pyskin.blender_armature_name]

        # Set bone bind_pose by inverting bindpose matrix
        if node_id in pyskin.joints:
            index_in_skel = pyskin.joints.index(node_id)
            inverse_bind_matrices = BinaryData.get_data_from_accessor(
                gltf, pyskin.inverse_bind_matrices)
            # Needed to keep scale in matrix, as bone.matrix seems to drop it
            if index_in_skel < len(inverse_bind_matrices):
                pynode.blender_bone_matrix = Conversion.matrix_gltf_to_blender(
                    inverse_bind_matrices[index_in_skel]).inverted()
                bone.matrix = pynode.blender_bone_matrix
            else:
                gltf.log.error("Error with inverseBindMatrix for skin " +
                               pyskin)
        else:
            print('No invBindMatrix for bone ' + str(node_id))
            pynode.blender_bone_matrix = Matrix()

        # Parent the bone
        if parent is not None and hasattr(gltf.data.nodes[parent],
                                          "blender_bone_name"):
            bone.parent = obj.data.edit_bones[gltf.data.nodes[
                parent].blender_bone_name]  #TODO if in another scene

        # Switch to Pose mode
        bpy.ops.object.mode_set(mode="POSE")
        obj.data.pose_position = 'POSE'

        # Set posebone location/rotation/scale (in armature space)
        # location is actual bone location minus it's original (bind) location
        bind_location = Matrix.Translation(
            pynode.blender_bone_matrix.to_translation())
        bind_rotation = pynode.blender_bone_matrix.to_quaternion()
        bind_scale = Conversion.scale_to_matrix(
            pynode.blender_bone_matrix.to_scale())

        location, rotation, scale = Conversion.matrix_gltf_to_blender(
            pynode.transform).decompose()
        if parent is not None and hasattr(gltf.data.nodes[parent],
                                          "blender_bone_matrix"):
            parent_mat = gltf.data.nodes[parent].blender_bone_matrix

            # Get armature space location (bindpose + pose)
            # Then, remove original bind location from armspace location, and bind rotation
            final_location = (bind_location.inverted() * parent_mat *
                              Matrix.Translation(location)).to_translation()
            obj.pose.bones[
                pynode.blender_bone_name].location = bind_rotation.inverted(
                ).to_matrix().to_4x4() * final_location

            # Do the same for rotation
            obj.pose.bones[pynode.blender_bone_name].rotation_quaternion = (
                bind_rotation.to_matrix().to_4x4().inverted() * parent_mat *
                rotation.to_matrix().to_4x4()).to_quaternion()
            obj.pose.bones[pynode.blender_bone_name].scale = (
                bind_scale.inverted() * parent_mat *
                Conversion.scale_to_matrix(scale)).to_scale()
        else:
            obj.pose.bones[
                pynode.blender_bone_name].location = bind_location.inverted(
                ) * location
            obj.pose.bones[
                pynode.
                blender_bone_name].rotation_quaternion = bind_rotation.inverted(
                ) * rotation
            obj.pose.bones[
                pynode.blender_bone_name].scale = bind_scale.inverted() * scale
Esempio n. 8
0
def projection(model, cage):

    model_mat = model.matrix_world.copy()
    cage_mat = cage.matrix_world.copy()
    cage_origo = cage_mat * cage.location

    cage_mesh = cage.data
    cage_verts = cage_mesh.vertices

    vertices = [cage_mat * vert.co for vert in cage.data.vertices]

    i = 0
    db = 0
    averageDist = 0.0
    noIntersectionPoints = []

    left_ear = [
        555, 558, 559, 729, 732, 733, 945, 1288, 1291, 1292, 1293, 1480, 1481
    ]
    right_ear = [
        528, 529, 531, 716, 719, 720, 1018, 1019, 1020, 1335, 1390, 1478, 1479
    ]

    #for 3 iter subdiv
    #left_ear = [2929, 2944, 2947, 2950, 2957, 2958, 2959, 3851, 3860, 3863, 3866, 3873, 3874, 3875, 4769, 5147, 5568, 5575, 5576, 5577, 5578, 5579, 5580, 5581, 5944, 5945]
    #right_ear = [2784, 2791, 2792, 2793, 2805, 2808, 2811, 3780, 3795, 3798, 3801, 3808, 3809, 3810, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 5357, 5679, 5806, 5942, 5943]

    for v in vertices:

        cage_vertex_in_model_system = model_mat.inverted() * v
        origo_in_model_system = model_mat.inverted() * cage_origo
        direction = origo_in_model_system - cage_vertex_in_model_system
        direction.normalize()

        result, location, normal, index = model.ray_cast(
            cage_vertex_in_model_system, direction)

        globalofresult = model_mat * location
        result_in_cage_system = cage_mat.inverted() * globalofresult

        if betweentwopoints(cage_vertex_in_model_system, origo_in_model_system,
                            location):

            translationMatrix = Matrix.Translation(
                (result_in_cage_system - cage_verts[i].co) / 1.05)
            cage_verts[i].co = translationMatrix * cage_verts[i].co
            averageDist = averageDist + numpy.linalg.norm(cage_origo -
                                                          cage_verts[i].co)
            db = db + 1
        else:
            noIntersectionPoints.append(i)

        i = i + 1

    averageDist = (averageDist / db) * 1.2

    for p in noIntersectionPoints:
        temp = cage_verts[p].co
        rate = 1.0 - (averageDist / numpy.linalg.norm(cage_origo - temp))
        translationMatrix = Matrix.Translation((cage_origo - temp) * rate)
        cage_verts[p].co = translationMatrix * cage_verts[p].co

    cage_details = bounds(model, False)

    for j in left_ear:
        temp = Vector((cage_details.x.min, 0, 0))
        temp = cage_mat.inverted() * temp
        cage_verts[j].co.x = temp[0]

    for j in right_ear:
        temp = Vector((cage_details.x.max, 0, 0))
        temp = cage_mat.inverted() * temp
        cage_verts[j].co.x = temp[0]

    return {'FINISHED'}
	def make_armature(self, context):
		bpy.ops.object.add(type='ARMATURE', enter_editmode=True, location=(0,0,0))
		armature = context.object
		armature.name = "skelton"
		armature.show_in_front = True
		
		bone_dic = {}
		def bone_add(name, head_pos, tail_pos, parent_bone=None):
			added_bone = armature.data.edit_bones.new(name)
			added_bone.head = head_pos
			added_bone.tail = tail_pos
			if parent_bone is not None:
				added_bone.parent = parent_bone
			bone_dic.update({name:added_bone})
			return added_bone
		def x_mirror_bones_add(base_name, right_head_pos, right_tail_pos, parent_bones):
			left_bone = bone_add(base_name + "_L", right_head_pos, right_tail_pos, parent_bones[0])
			right_bone = bone_add(base_name + "_R",
									[pos*axis for pos, axis in zip(right_head_pos, (-1, 1, 1))],
									[pos*axis for pos, axis in zip(right_tail_pos, (-1, 1, 1))],
									parent_bones[1]
								)
			return left_bone,right_bone
		def x_add(posA, add_x):
			pos = [pA + _add for pA, _add in zip(posA, [add_x, 0, 0])]
			return pos
		def y_add(posA, add_y):
			pos = [pA + _add for pA, _add in zip(posA, [0, add_y, 0])]
			return pos
		def z_add(posA, add_z):
			pos = [pA+_add for pA,_add in zip(posA,[0,0,add_z])]
			return pos

		root = bone_add("root", (0, 0, 0), (0, 0,0.3))
		head_size = self.tall / self.head_ratio
		#down side (前は8頭身の時の股上/股下の股下側割合、後ろは4頭身のときの〃を年齢具合で線形補完)(股上高めにすると破綻する)
		eight_upside_ratio, four_upside_ratio = 1-self.leg_length_ratio, (2.5/4)*(1-self.aging_ratio)+(1-self.leg_length_ratio)*self.aging_ratio
		hip_up_down_ratio = eight_upside_ratio * (1 - (8 - self.head_ratio) / 4) + four_upside_ratio * (8 - self.head_ratio) / 4
		#チェスト下とチェスト~首の割合
		upper_chest_neck_ratio = (1-(8-self.head_ratio)/4)*(1/3) + ((8-self.head_ratio)/4)*0.1

		#体幹 
		neck_len = (1-upper_chest_neck_ratio)*(self.tall*(1-hip_up_down_ratio)/2)/3
		upper_chest_len =  (self.tall*hip_up_down_ratio - head_size - neck_len)/3
		chest_len = upper_chest_len
		spine_len = chest_len
		
		Hips = bone_add("Hips", (0,0, self.tall*(1-hip_up_down_ratio) ), (0,0.1,self.tall*(1-hip_up_down_ratio)),root)
		Spine = bone_add("Spine",Hips.head,z_add(Hips.head,spine_len),Hips)
		Chest = bone_add("Chest", Spine.tail, z_add(Spine.tail,chest_len), Spine)
		upperChest = bone_add("upperChest", Chest.tail, z_add(Chest.tail,upper_chest_len), Chest)
		Neck = bone_add("Neck", upperChest.tail, z_add(upperChest.tail,neck_len), upperChest)
		Head = bone_add("Head", (0,0, self.tall-head_size), (0,0, self.tall), Neck)

		#目
		eye_depth = self.eye_depth
		eyes = x_mirror_bones_add("eye", (head_size / 5, 0, 		Head.head[2] + head_size / 2),
										 (head_size / 5, eye_depth, Head.head[2] + head_size / 2),
										 (Head, Head))
		#足
		leg_width = self.leg_width
		leg_size = self.leg_size
		
		leg_bone_lengh =( self.tall*(1-hip_up_down_ratio) - self.tall*0.05 )/2
		upside_legs = x_mirror_bones_add("Upper_Leg",
				x_add(Hips.head, leg_width),
				z_add(x_add(Hips.head, leg_width), -leg_bone_lengh),
				 (Hips, Hips)
				)
		lower_legs = x_mirror_bones_add("Lower_Leg",
				upside_legs[0].tail,
				(leg_width,0,self.tall*0.05),
				upside_legs
				)
		Foots = x_mirror_bones_add("Foot",
				lower_legs[0].tail,
				(leg_width,-leg_size*(2/3),0),
				lower_legs
				)
		Toes = x_mirror_bones_add("Toes",
				Foots[0].tail,
				(leg_width,-leg_size,0),
				Foots
				)						
		
		#肩~指
		shoulder_in_pos = self.shoulder_in_width / 2
		
		shoulders = x_mirror_bones_add("shoulder",
			x_add(upperChest.tail, shoulder_in_pos),
			x_add(upperChest.tail, shoulder_in_pos + self.shoulder_width),
			(upperChest,upperChest))

		arm_lengh = head_size * (1*(1-(self.head_ratio-6)/2)+1.5*((self.head_ratio-6)/2)) * self.arm_length_ratio
		arms = x_mirror_bones_add("Arm",
			shoulders[0].tail,
			x_add(shoulders[0].tail,arm_lengh),
			shoulders)
		hand_size = self.hand_size
		forearms = x_mirror_bones_add("forearm",
			arms[0].tail,
			#グーにするとパーの半分くらいになる、グーのとき手を含む下腕の長さと上腕の長さが概ね一緒
			x_add(arms[0].tail,arm_lengh - hand_size/2),
			arms)
		hands = x_mirror_bones_add("hand",
			forearms[0].tail,
			x_add(forearms[0].tail,hand_size/2),
			forearms
		)

		def fingers(finger_name,proximal_pos,finger_len_sum):

			finger_normalize = 1/(self.finger_1_2_ratio*self.finger_2_3_ratio+self.finger_1_2_ratio+1)
			proximal_finger_len = finger_len_sum*finger_normalize
			intermediate_finger_len = finger_len_sum*finger_normalize*self.finger_1_2_ratio
			distal_finger_len = finger_len_sum*finger_normalize*self.finger_1_2_ratio*self.finger_2_3_ratio
			proximal_bones = x_mirror_bones_add(f"{finger_name}_proximal",proximal_pos,x_add(proximal_pos,proximal_finger_len),hands)
			intermediate_bones = x_mirror_bones_add(f"{finger_name}_intermidiate",proximal_bones[0].tail,x_add(proximal_bones[0].tail,intermediate_finger_len),proximal_bones)
			distal_bones = x_mirror_bones_add(f"{finger_name}_distal",intermediate_bones[0].tail,x_add(intermediate_bones[0].tail,distal_finger_len),intermediate_bones)
			return proximal_bones,intermediate_bones,distal_bones

		finger_y_offset = -hand_size/10
		thumbs = fingers(
			"finger_thumbs",
			y_add(hands[0].head,finger_y_offset - hand_size/5),
			hand_size/2
		)

		mats = [thumbs[0][i].matrix.translation for i in [0,1]]
		mats = [Matrix.Translation(mat) for mat in mats]
		for j in range(3):
			for n,angle in enumerate([-45,45]):
				thumbs[j][n].transform( mats[n].inverted() )
				thumbs[j][n].transform( Matrix.Rotation(radians(angle),4,"Z") )
				thumbs[j][n].transform( mats[n] )

		index_fingers = fingers(
			"finger_index",
			y_add(hands[0].tail,-hand_size/5 +finger_y_offset),
			(hand_size/2)-(1/2.3125)*(hand_size/2)/3
		)
		middle_fingers = fingers(
			"finger_middle",
			y_add(hands[0].tail,finger_y_offset),
			hand_size/2
		)
		ring_fingers = fingers(
			"finger_ring",
			y_add(hands[0].tail,hand_size/5 +finger_y_offset),
			(hand_size/2)-(1/2.3125)*(hand_size/2)/3
		)
		little_fingers = fingers(
			"finger_little",
			y_add(hands[0].tail,2*hand_size/5 +finger_y_offset),
			((hand_size/2)-(1/2.3125)*(hand_size/2)/3) * ((1/2.3125)+(1/2.3125)*0.75)
		)

		#'s is left,right tupple
		body_dict = {
			"hips":Hips.name,
			"spine":Spine.name,
			"chest":Chest.name,
			"upperChest":upperChest.name,
			"neck":Neck.name,
			"head":Head.name
		}
		left_right_body_dict = {
			f"{left_right}{bone_name}":bones[lr].name
			for bone_name,bones in {
				"Eye":eyes,
				"UpperLeg":upside_legs,
				"LowerLeg":lower_legs,
				"Foot":Foots,
				"Toes":Toes,
				"Shoulder":shoulders,
				"UpperArm":arms,
				"LowerArm":forearms,
				"Hand":hands
			}.items()
			for lr,left_right in enumerate(["left","right"])
		}

		#VRM finger like name key
		fingers_dict={
			f"{left_right}{finger_name}{position}":finger[i][lr].name
			for finger_name,finger in zip(["Thumb","Index","Middle","Ring","Little"],[thumbs,index_fingers,middle_fingers,ring_fingers,little_fingers])
			for i,position in enumerate(["Proximal","Intermediate","Distal"])
			for lr,left_right in enumerate(["left","right"])
		}

		#VRM bone name : blender bone name
		bone_name_all_dict = {}
		bone_name_all_dict.update(body_dict)
		bone_name_all_dict.update(left_right_body_dict)
		bone_name_all_dict.update(fingers_dict)

		context.scene.update()
		bpy.ops.object.mode_set(mode='OBJECT')
		return armature,bone_name_all_dict
Esempio n. 10
0
def read_chan(context, filepath, z_up, rot_ord, sensor_width, sensor_height):

    # get the active object
    scene = context.scene
    obj = context.active_object
    camera = obj.data if obj.type == 'CAMERA' else None

    # prepare the correcting matrix
    rot_mat = Matrix.Rotation(radians(90.0), 4, 'X').to_4x4()

    # read the file
    filehandle = open(filepath, 'r')

    # iterate throug the files lines
    for line in filehandle:
        # reset the target objects matrix
        # (the one from whitch one we'll extract the final transforms)
        m_trans_mat = Matrix()

        # strip the line
        data = line.split()

        # test if the line is not commented out
        if data and not data[0].startswith("#"):

            # set the frame number basing on the chan file
            scene.frame_set(int(data[0]))

            # read the translation values from the first three columns of line
            v_transl = Vector((float(data[1]), float(data[2]), float(data[3])))
            translation_mat = Matrix.Translation(v_transl)
            translation_mat.to_4x4()

            # read the rotations, and set the rotation order basing on the
            # order set during the export (it's not being saved in the chan
            # file you have to keep it noted somewhere
            # the actual objects rotation order doesn't matter since the
            # rotations are being extracted from the matrix afterwards
            e_rot = Euler((radians(float(data[4])), radians(float(data[5])),
                           radians(float(data[6]))))
            e_rot.order = rot_ord
            mrot_mat = e_rot.to_matrix()
            mrot_mat.resize_4x4()

            # merge the rotation and translation
            m_trans_mat = translation_mat * mrot_mat

            # correct the world space
            # (nuke's and blenders scene spaces are different)
            if z_up:
                m_trans_mat = rot_mat * m_trans_mat

            # break the matrix into a set of the coordinates
            trns = m_trans_mat.decompose()

            # set the location and the location's keyframe
            obj.location = trns[0]
            obj.keyframe_insert("location")

            # convert the rotation to euler angles (or not)
            # basing on the objects rotation mode
            if obj.rotation_mode == 'QUATERNION':
                obj.rotation_quaternion = trns[1]
                obj.keyframe_insert("rotation_quaternion")
            elif obj.rotation_mode == 'AXIS_ANGLE':
                tmp_rot = trns[1].to_axis_angle()
                obj.rotation_axis_angle = (tmp_rot[1], ) + tmp_rot[0][:]
                obj.keyframe_insert("rotation_axis_angle")
                del tmp_rot
            else:
                obj.rotation_euler = trns[1].to_euler(obj.rotation_mode)
                obj.keyframe_insert("rotation_euler")

            # check if the object is camera and fov data is present
            if camera and len(data) > 7:
                camera.sensor_fit = 'HORIZONTAL'
                camera.sensor_width = sensor_width
                camera.sensor_height = sensor_height
                camera.angle_y = radians(float(data[7]))
                camera.keyframe_insert("lens")
    filehandle.close()

    return {'FINISHED'}
Esempio n. 11
0
def draw_brick(cm_id, bricksdict, key, loc, seed_keys, bcoll,
               clear_existing_collection, parent, dimensions, zstep,
               brick_size, brick_type, split, last_split_model, custom_object1,
               custom_object2, custom_object3, mat_dirty, custom_data,
               brick_scale, bricks_created, all_meshes, logo, mats, brick_mats,
               internal_mat, brick_height, logo_resolution, logo_decimate,
               build_is_dirty, material_type, custom_mat, random_mat_seed,
               stud_detail, exposed_underside_detail, hidden_underside_detail,
               random_rot, random_loc, logo_type, logo_scale, logo_inset,
               circle_verts, instance_method, rand_s1, rand_s2, rand_s3):
    brick_d = bricksdict[key]
    # check exposure of current [merged] brick
    if brick_d["top_exposed"] is None or brick_d[
            "bot_exposed"] is None or build_is_dirty:
        top_exposed, bot_exposed = set_all_brick_exposures(
            bricksdict, zstep, key)
    else:
        top_exposed, bot_exposed = is_brick_exposed(bricksdict, zstep, key)

    # get brick material
    mat = get_material(bricksdict,
                       key,
                       brick_size,
                       zstep,
                       material_type,
                       custom_mat,
                       random_mat_seed,
                       mat_dirty,
                       seed_keys,
                       brick_mats=brick_mats)

    # set up arguments for brick mesh
    use_stud = (top_exposed and stud_detail != "NONE") or stud_detail == "ALL"
    logo_to_use = logo if use_stud else None
    underside_detail = exposed_underside_detail if bot_exposed else hidden_underside_detail

    ### CREATE BRICK ###

    # add brick with new mesh data at original location
    if brick_d["type"].startswith("CUSTOM"):
        m = custom_data[int(brick_d["type"][-1]) - 1]
    else:
        # get brick mesh
        m = get_brick_data(brick_d, rand_s3, dimensions, brick_size,
                           brick_type, brick_height, logo_resolution,
                           logo_decimate, circle_verts, underside_detail,
                           logo_to_use, logo_type, logo_scale, logo_inset,
                           use_stud)
    # duplicate data if not instancing by mesh data
    m = m if instance_method == "LINK_DATA" else m.copy()
    # apply random rotation to edit mesh according to parameters
    random_rot_matrix = get_random_rot_matrix(random_rot, rand_s2, brick_size)
    # get brick location
    loc_offset = get_random_loc(random_loc, rand_s2, dimensions["half_width"],
                                dimensions["half_height"])
    brick_loc = get_brick_center(bricksdict, key, zstep, loc) + loc_offset

    if split:
        brick = bpy.data.objects.get(brick_d["name"])
        edge_split = use_edge_split_mod(brick_d, custom_object1,
                                        custom_object2, custom_object3)
        if brick:
            # NOTE: last brick object is left in memory (faster)
            # set brick.data to new mesh (resets materials)
            brick.data = m
            # add/remove edge split modifier if necessary
            e_mod = brick.modifiers.get("Edge Split")
            if not e_mod and edge_split:
                add_edge_split_mod(brick)
            elif e_mod and not edge_split:
                brick.modifiers.remove(e_mod)
        else:
            # create new object with mesh data
            brick = bpy.data.objects.new(brick_d["name"], m)
            brick.cmlist_id = cm_id
            # add edge split modifier
            if edge_split:
                add_edge_split_mod(brick)
        # rotate brick by random rotation
        if random_rot_matrix is not None:
            # resets rotation_euler in case object is reused
            brick.rotation_euler = (0, 0, 0)
            brick.rotation_euler.rotate(random_rot_matrix)
        # set brick location
        brick.location = brick_loc
        # set brick material
        mat = mat or internal_mat
        set_material(brick, mat)
        if mat:
            keys_in_brick = get_keys_in_brick(bricksdict, brick_size, zstep,
                                              loc)
            for k in keys_in_brick:
                bricksdict[k]["mat_name"] = mat.name
        # append to bricks_created
        bricks_created.append(brick)
        # set remaining brick info if brick object just created
        brick.parent = parent
        if not brick.is_brick:
            brick.is_brick = True
        # link bricks to brick collection
        if clear_existing_collection or brick.name not in bcoll.objects.keys():
            bcoll.objects.link(brick)
    else:
        # duplicates mesh – prevents crashes in 2.79 (may need to add back if experiencing crashes in b280)
        if not b280():
            m = m.copy()
        # apply rotation matrices to edit mesh
        if random_rot_matrix is not None:
            m.transform(random_rot_matrix)
        # transform brick mesh to coordinate on matrix
        m.transform(Matrix.Translation(brick_loc))

        # set to internal mat if material not set
        internal = False
        if mat is None:
            mat = internal_mat
            internal = True

        # keep track of mats already used
        if mat in mats:
            mat_idx = mats.index(mat)
        elif mat is not None:
            mats.append(mat)
            mat_idx = len(mats) - 1

        # set material
        if mat is not None:
            # set material name in dictionary
            if not internal:
                brick_d["mat_name"] = mat.name
            # point all polygons to target material (index will correspond in all_meshes object)
            for p in m.polygons:
                p.material_index = mat_idx

        # append mesh to all_meshes bmesh object
        all_meshes.from_mesh(m)

        # remove mesh in 2.79 (mesh was duplicated above to prevent crashes)
        if not b280():
            bpy.data.meshes.remove(m)
        # NOTE: The following lines clean up the mesh if not duplicated
        else:
            # reset polygon material mapping
            if mat is not None:
                for p in m.polygons:
                    p.material_index = 0

            # reset transformations for reference mesh
            m.transform(Matrix.Translation(-brick_loc))
            if random_rot_matrix is not None:
                random_rot_matrix.invert()
                m.transform(random_rot_matrix)

    return bricksdict
Esempio n. 12
0
    def __init__(self, cont):

        # store the owner, mesh, material id, frequency
        # get sprite size and Vector coordinates from string property "sprites"
        # convert string property "sequence" to an array of valid id's
        # get data from string properties "spin", "loop" and "pingpong"
        # initialize direction, id and offset

        def get_mesh(self):
            mesh = self.own.meshes[0]
            try:
                base_obj = self.own.scene.objectsInactive[self.own.name]
            except KeyError:
                if not self.own["unlink"]:
                    return mesh
            if not hasattr(logic, "libnews"):
                logic.libnews = 0
            mesh_name = mesh.name
            new_mesh = logic.LibNew(mesh_name + str(logic.libnews), "Mesh",
                                    [mesh_name])[0]
            self.own.replaceMesh(new_mesh)
            logic.libnews += 1
            return new_mesh

        def get_mat_id(mesh, identifier="_UV"):

            # get the material(s) that will be affected
            # if needed you can change the identifier
            # if the identifier is not found, all materials on the mesh will be affected

            for mat_id in range(mesh.numMaterials):
                if identifier in mesh.getMaterialName(mat_id):
                    return mat_id
            return -1

        def get_sprite_data(self):
            sprites = [int(i) for i in self.own["sprites"].split(", ")]
            sprite_size = Vector([1 / sprites[i] for i in range(2)]).to_3d()
            sprite_coords = []
            for y in range(sprites[1]):
                for x in range(sprites[0]):
                    sprite_coords.append(
                        Vector([x * sprite_size[0],
                                y * sprite_size[1]]).to_3d())
            return sprite_coords, sprite_size

        def get_sequence(string):
            def digit_in_range(s, len):
                if not s.isdigit():
                    return "ValueError"
                d = int(s)
                if not d < len:
                    return "IndexError"
                return d

            def digits_in_range(l, len):
                return [digit_in_range(s, len) for s in l]

            sequence = []
            num_sprites = len(self.sprite_coords)
            for s in [
                    s for s in string.replace(" ", "").split(",") if s != ""
            ]:
                if "-" in s:
                    ds = digits_in_range(s.split("-"), num_sprites)
                    if "ValueError" in ds:
                        self.errors.append(self.err_value + s)
                    elif "IndexError" in ds:
                        self.errors.append(self.err_index + s)
                    else:
                        first, last = ds
                        dir = -1 if first > last else 1
                        for i in range(first, last + dir, dir):
                            sequence.append(i)
                elif "*" in s:
                    ds = digits_in_range(s.split("*"), num_sprites)
                    if "ValueError" in ds:
                        self.errors.append(self.err_value + s)
                    elif "IndexError" in ds:
                        self.errors.append(self.err_index + s)
                    else:
                        id, num = ds
                        for i in range(num):
                            sequence.append(id)
                else:
                    d = digit_in_range(s, num_sprites)
                    if d == "ValueError":
                        self.errors.append(self.err_value + s)
                    elif d == "IndexError":
                        self.errors.append(self.err_index + s)
                    else:
                        sequence.append(d)

            return sequence

        def get_properties(self):
            sequence = get_sequence(self.own["sequence"])
            loop = self.own["loop"]
            pingpong = self.own["pingpong"]
            return sequence, loop, pingpong

        self.own = cont.owner
        self.err_value = "UV Scroll Sequence contains illegal value:\t"
        self.err_index = "UV Scroll Sequence index is out of range:\t"
        self.errors = []
        self.sprite_coords, self.sprite_size = get_sprite_data(self)
        self.sequence, self.loop, self.pingpong = get_properties(self)

        if self.errors:
            err_msg = "ERROR:\t" + self.own.name
            for e in self.errors:
                err_msg += "\n\t-> " + e
            print(err_msg)
            return

        self.mesh = get_mesh(self)
        self.mat_id = get_mat_id(self.mesh)
        self.always = cont.sensors[0]
        self.freq = self.always.skippedTicks
        self.num_sequence = len(self.sequence)
        self.extremes = [0, self.num_sequence - 1]
        self.direction = 1
        self.end = False
        self.id = 0
        self.offset = Matrix.Translation(
            self.sprite_coords[self.sequence[self.id]])
Esempio n. 13
0
 def get_offset(self, next_id):
     if not self.sequence:
         return Matrix.Identity(4)
     current_coords = self.sprite_coords[self.sequence[self.id]]
     next_coords = self.sprite_coords[self.sequence[next_id]]
     return Matrix.Translation(next_coords - current_coords)
Esempio n. 14
0
def main(context, import_filename, options):
    print("execute amf import")

    IMPORT_SCALE = options.get_scale_multiplier()
    print(f"importing at scale {IMPORT_SCALE}")

    bitmapsDir = ospath.split(import_filename)[0]
    if len(options.DIRECTORY_BITMAP) > 0:
        bitmapsDir = options.DIRECTORY_BITMAP

    reader = FileReader(import_filename)

    model = AmfModel(reader)

    arm_obj = None
    armature = None
    model_nodes = []
    model_materials = []

    if options.IMPORT_BONES and len(model.nodes) > 0:
        print("creating bones")
        bpy.ops.object.add(type='ARMATURE', enter_editmode=True)
        arm_obj = context.object
        armature = arm_obj.data
        armature.name = model.name + " armature"

        node_abs_transforms = options.get_node_transforms(
            model.nodes, 0.5)  #why is this getting doubled somehow?
        for i, node in enumerate(model.nodes):
            bone = armature.edit_bones.new(options.PREFIX_BONE + node.name)
            if node.parent_index >= 0:
                bone.parent = model_nodes[node.parent_index]
            bone.tail = Vector([1, 0, 0]) * IMPORT_SCALE

            #'bone.transform' only applies rotation
            bone.transform(node_abs_transforms[i], scale=False)
            bone.translate(node_abs_transforms[i].translation)
            model_nodes.append(bone)

        bpy.ops.object.mode_set(mode='OBJECT')

    if options.IMPORT_MARKERS and len(model.markers) > 0:
        print("creating markers")
        for mg in model.markers:
            marker_name = options.PREFIX_MARKER + mg.name
            node_abs_transforms = options.get_node_transforms(model.nodes)
            for m in mg.markers:
                if options.MODE_MARKERS == 'MESH':
                    mesh = bpy.data.meshes.new(marker_name)
                    marker_obj = bpy.data.objects.new(marker_name, mesh)

                    bm = bmesh.new()
                    bmesh.ops.create_uvsphere(bm,
                                              u_segments=16,
                                              v_segments=16,
                                              diameter=IMPORT_SCALE)
                    bm.to_mesh(mesh)
                    bm.free()

                    context.scene.collection.objects.link(marker_obj)
                else:  # MODE_MARKERS == 'EMPTY'
                    #it says 'radius' but it comes out the same size as uvsphere's diameter
                    bpy.ops.object.empty_add(type='SPHERE',
                                             radius=IMPORT_SCALE)
                    marker_obj = context.object
                    marker_obj.name = marker_name

                marker_transform = Matrix.Translation(
                    m.position *
                    IMPORT_SCALE) @ m.rotation.to_matrix().to_4x4()
                if m.node_index >= 0:
                    marker_transform = node_abs_transforms[
                        m.node_index] @ marker_transform
                    if options.IMPORT_BONES:
                        marker_obj.parent = arm_obj
                        marker_obj.parent_type = 'BONE'
                        marker_obj.parent_bone = options.PREFIX_BONE + model.nodes[
                            m.node_index].name

                marker_obj.hide_render = True
                marker_obj.matrix_world = marker_transform

    if options.IMPORT_MATERIALS and len(model.materials) > 0:
        print("creating materials")
        for mat in model.materials:
            material = bpy.data.materials.new(mat.name)
            material.use_nodes = True

            bsdf = material.node_tree.nodes["Principled BSDF"]

            texture = material.node_tree.nodes.new('ShaderNodeTexImage')
            texture_path = mat.textures[0].get_full_path(
                bitmapsDir, options.SUFFIX_BITMAP)
            if not mat.textures[0].is_null and texture_path.exists():
                texture.image = bpy.data.images.load(str(texture_path))
                if not mat.is_transparent:
                    texture.image.alpha_mode = 'CHANNEL_PACKED'
                    material.node_tree.links.new(bsdf.inputs['Specular'],
                                                 texture.outputs['Alpha'])

            material.node_tree.links.new(bsdf.inputs['Base Color'],
                                         texture.outputs['Color'])
            bsdf.location = [0, 300]
            texture.location = [-300, 300]

            #           texture.repeat_x = mat.textures[0].uv_tiles[0]
            #           texture.repeat_y = mat.textures[0].uv_tiles[1]

            if not mat.is_terrain and not mat.textures[3].is_null:
                texture = material.node_tree.nodes.new('ShaderNodeTexImage')
                texture_path = mat.textures[3].get_full_path(
                    bitmapsDir, options.SUFFIX_BITMAP)
                if texture_path.exists():
                    texture.image = bpy.data.images.load(str(texture_path))
                    texture.image.alpha_mode = 'NONE'
                    texture.image.colorspace_settings.name = 'Non-Color'

                # inverting green channel is necessary to convert from DirectX coordsys to OpenGL

                bump = material.node_tree.nodes.new('ShaderNodeNormalMap')
                split = material.node_tree.nodes.new('ShaderNodeSeparateRGB')
                invert = material.node_tree.nodes.new('ShaderNodeInvert')
                merge = material.node_tree.nodes.new('ShaderNodeCombineRGB')

                texture.location = [-1100, -100]
                split.location = [-800, -100]
                invert.location = [-600, -200]
                merge.location = [-400, -100]
                bump.location = [-200, -100]

                material.node_tree.links.new(split.inputs['Image'],
                                             texture.outputs['Color'])
                material.node_tree.links.new(invert.inputs['Color'],
                                             split.outputs['G'])
                material.node_tree.links.new(merge.inputs['R'],
                                             split.outputs['R'])
                material.node_tree.links.new(merge.inputs['G'],
                                             invert.outputs['Color'])
                material.node_tree.links.new(merge.inputs['B'],
                                             split.outputs['B'])
                material.node_tree.links.new(bump.inputs['Color'],
                                             merge.outputs['Image'])
                material.node_tree.links.new(bsdf.inputs['Normal'],
                                             bump.outputs['Normal'])

            model_materials.append(material)

    if options.IMPORT_MESHES and len(model.regions) > 0:
        print("creating meshes")
        instance_lookup = dict()
        for region in model.regions:
            for perm in region.permutations:
                index_buffer = model.index_buffers[perm.face_address]
                position_buffer = [
                    v.position for v in model.vertex_buffers[perm.vert_address]
                ]
                texcoord_buffer = [
                    v.texcoords
                    for v in model.vertex_buffers[perm.vert_address]
                ]
                normal_buffer = [
                    v.normal for v in model.vertex_buffers[perm.vert_address]
                ]
                node_index_buffer = [
                    v.indices for v in model.vertex_buffers[perm.vert_address]
                ]
                node_weight_buffer = [
                    v.weights for v in model.vertex_buffers[perm.vert_address]
                ]

                for sub_index, sub in enumerate(perm.submeshes):
                    instance_key = f"{perm.vert_address}_{sub_index:03d}"
                    root_obj = instance_lookup.get(instance_key, None)
                    if root_obj is not None:
                        mesh_obj = root_obj.copy()
                        #this makes a deep copy rather than a linked copy
                        #mesh_obj.data = root_obj.data.copy()
                        mesh_obj.matrix_world = options.get_perm_transform(
                            perm)
                        context.scene.collection.objects.link(mesh_obj)

                        if options.MODE_MESHES == 'JOIN':
                            break  #skip the rest of the submeshes
                        else:
                            continue

                    if options.MODE_MESHES == 'JOIN':
                        mesh_name = f"{region.name}:{perm.name}"
                        mesh_verts = position_buffer
                        mesh_faces = index_buffer
                        mesh_coords = [
                            texcoord_buffer[i]
                            for i in itertools.chain(*mesh_faces)
                        ]  #blender wants 3 uvs per tri, rather than one per vertex
                        mesh_norms = normal_buffer
                        mesh_nodes = node_index_buffer
                        mesh_weights = node_weight_buffer
                        mat_ranges = [(s.face_start, s.face_count, s.mat_index)
                                      for s in perm.submeshes]
                    else:
                        mesh_name = f"{region.name}:{perm.name}.{sub_index:03d}"
                        mesh_faces = [
                            index_buffer[i]
                            for i in range(sub.face_start, sub.face_start +
                                           sub.face_count)
                        ]
                        mesh_coords = [
                            texcoord_buffer[i]
                            for i in itertools.chain(*mesh_faces)
                        ]  #blender wants 3 uvs per tri, rather than one per vertex

                        min_index = min(itertools.chain(*mesh_faces))
                        max_index = max(itertools.chain(*mesh_faces))

                        mesh_verts = [
                            position_buffer[i]
                            for i in range(min_index, max_index + 1)
                        ]  #only need verts referenced by the current faces
                        mesh_norms = [
                            normal_buffer[i]
                            for i in range(min_index, max_index + 1)
                        ]

                        if perm.vert_format > 0:
                            mesh_nodes = [
                                node_index_buffer[i]
                                for i in range(min_index, max_index + 1)
                            ]
                            mesh_weights = [
                                node_weight_buffer[i]
                                for i in range(min_index, max_index + 1)
                            ]

                        mat_ranges = [
                            (0, sub.face_count, sub.mat_index)
                        ]  #split meshes are offset to always start at 0

                        # translate the face indices to start at 0 since we are only using a subset of the vertices now
                        for face in mesh_faces:
                            face[0] -= min_index
                            face[1] -= min_index
                            face[2] -= min_index

                    mesh = bpy.data.meshes.new(mesh_name)
                    mesh.from_pydata(mesh_verts, [], mesh_faces)
                    mesh_obj = bpy.data.objects.new(mesh_name, mesh)

                    mesh.normals_split_custom_set_from_vertices(mesh_norms)
                    mesh.use_auto_smooth = True  #required for custom normals to take effect

                    if options.IMPORT_MATERIALS:
                        mat_lookup = dict()
                        for i, mat_index in enumerate(
                                set(t[2] for t in mat_ranges)):
                            mat_lookup[mat_index] = i

                        for i in mat_lookup.keys():
                            mesh.materials.append(model_materials[i])

                        for face_start, face_count, mat_index in mat_ranges:
                            for i in range(face_start,
                                           face_start + face_count):
                                mesh.polygons[i].material_index = mat_lookup[
                                    mat_index]

                    uvmap = mesh.uv_layers.new()
                    for i in range(len(mesh_coords)):
                        uvmap.data[i].uv = mesh_coords[i]

                    if options.IMPORT_BONES and perm.vert_format > 0:
                        mesh_obj.parent = arm_obj
                        mod = mesh_obj.modifiers.new("armature", 'ARMATURE')
                        mod.object = arm_obj

                        for node in model.nodes:
                            mesh_obj.vertex_groups.new(name=node.name)

                        if perm.node_index != 255:
                            for i in range(len(mesh_verts)):
                                mesh_obj.vertex_groups[perm.node_index].add(
                                    [i], 1.0, 'ADD')
                        else:
                            for i in range(len(mesh_nodes)):
                                indices = mesh_nodes[i]
                                weights = mesh_weights[i]
                                for j in range(len(indices)):
                                    if weights[j] == 0:
                                        continue
                                    mesh_obj.vertex_groups[int(
                                        indices[j])].add([i], weights[j],
                                                         'ADD')

                    if not math.isnan(perm.scale):
                        mesh_obj.matrix_world = options.get_perm_transform(
                            perm)
                        instance_lookup[instance_key] = mesh_obj

                    mesh.transform(Matrix.Scale(IMPORT_SCALE, 4))
                    context.scene.collection.objects.link(mesh_obj)

                    if options.MODE_MESHES == 'JOIN':
                        break  #skip the rest of the submeshes

    reader.close()
    def process(self):
        # inputs
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not any(
                self.outputs[name].is_linked for name in
            ['Vertices', 'Edges', 'Polygons', 'ExtrudedPolys', 'OtherPolys']):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Polygons'].sv_get(default=[[]])
        masks_s = self.inputs['Mask'].sv_get(default=[[1]])
        heights_s = self.inputs['Height'].sv_get()
        scales_s = self.inputs['Scale'].sv_get()

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s])

        offset = 0
        for vertices, edges, faces, masks, heights, scales in zip(*meshes):
            fullList(heights, len(faces))
            fullList(scales, len(faces))
            fullList(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces)
            extruded_faces = bmesh.ops.extrude_discrete_faces(
                bm, faces=bm.faces)['faces']

            new_extruded_faces = []

            for face, mask, height, scale in zip(extruded_faces, masks,
                                                 heights, scales):
                if not mask:
                    continue
                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                rotation = face.normal.rotation_difference(
                    (0, 0, 1)).to_matrix().to_4x4()
                #rotation = autorotate(z, face.normal).inverted()
                m = translation * rotation
                bmesh.ops.scale(bm,
                                vec=(scale, scale, scale),
                                space=m.inverted(),
                                verts=face.verts)
                bmesh.ops.translate(bm, verts=face.verts, vec=dr)

                new_extruded_faces.append([v.index for v in face.verts])

            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()
            new_other_faces = [
                f for f in new_faces if f not in new_extruded_faces
            ]

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
        if self.outputs['ExtrudedPolys'].is_linked:
            self.outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        if self.outputs['OtherPolys'].is_linked:
            self.outputs['OtherPolys'].sv_set(result_other_faces)
def load_file(context, filepath, report, fix_parents, game_version, jms_path_a,
              jms_path_b):
    jms_a_transform = False
    jms_b_transform = False

    jma_file = JMAAsset(filepath, game_version, report)
    if path.exists(jms_path_a):
        jms_a_transform = True
        jms_a_file = import_jms.JMSAsset(jms_path_a, "halo2")
    if path.exists(jms_path_a) and path.exists(jms_path_b):
        jms_b_transform = True
        jms_b_file = import_jms.JMSAsset(jms_path_b, "halo2")

    collection = bpy.context.collection
    scene = bpy.context.scene
    view_layer = bpy.context.view_layer
    armature = None
    object_list = list(scene.objects)

    scene_nodes = []
    jma_nodes = []
    jms_a_nodes = []
    jms_b_nodes = []
    for obj in object_list:
        if armature is None:
            if obj.type == 'ARMATURE':
                is_armature_good = False
                if jma_file.version == 16390:
                    if len(obj.data.bones) == jma_file.node_count:
                        is_armature_good = True
                else:
                    exist_count = 0
                    armature_bone_list = list(obj.data.bones)
                    for node in armature_bone_list:
                        for jma_node in jma_file.nodes:
                            if node.name == jma_node.name:
                                scene_nodes.append(node.name)
                                exist_count += 1
                    if exist_count == len(jma_file.nodes):
                        is_armature_good = True

                if is_armature_good:
                    armature = obj
                    view_layer.objects.active = armature

    for jma_node in jma_file.nodes:
        jma_nodes.append(jma_node.name)

    if len(scene_nodes) > 0:
        for jma_node in jma_nodes:
            if not jma_node in scene_nodes:
                report({'WARNING'},
                       "Node '%s' not found in an existing armature" %
                       jma_node)

    if armature == None:
        if not jma_file.broken_skeleton:
            if jma_file.version >= 16392:
                if jms_a_transform and not jms_b_transform:
                    for jms_node in jms_a_file.nodes:
                        jms_a_nodes.append(jms_node.name)

                    for jms_node_name in jms_a_nodes:
                        if not jms_node_name in jma_nodes:
                            jms_a_transform = False
                            report({
                                'WARNING'
                            }, "Node '%s' from JMS skeleton not found in JMA skeleton."
                                   % jms_node_name)

                    report({
                        'WARNING'
                    }, "No valid armature detected. One will be created and the referenced JMS will be used for the rest position"
                           )

                elif jms_a_transform and jms_b_transform:
                    for jms_node in jms_a_file.nodes:
                        jms_a_nodes.append(jms_node.name)

                    for jms_node in jms_b_file.nodes:
                        jms_b_nodes.append(jms_node.name)

                    jms_nodes = jms_a_nodes + jms_b_nodes

                    for jms_node_name in jms_nodes:
                        if not jms_node_name in jma_nodes:
                            jms_a_transform = False
                            report({
                                'WARNING'
                            }, "Node '%s' from JMS skeleton not found in JMA skeleton."
                                   % jms_node_name)

                    report({
                        'WARNING'
                    }, "No valid armature detected. One will be created and the referenced JMS files will be used for the rest position"
                           )

                else:
                    report({
                        'WARNING'
                    }, "No valid armature detected. One will be created but expect issues with visuals in scene due to no proper rest position"
                           )

                pelvis = None
                thigh0 = None
                thigh1 = None
                spine1 = None
                clavicle0 = None
                clavicle1 = None

                armdata = bpy.data.armatures.new('Armature')
                ob_new = bpy.data.objects.new('Armature', armdata)
                collection.objects.link(ob_new)
                armature = ob_new
                view_layer.objects.active = armature
                if fix_parents:
                    if game_version == 'halo2':
                        for idx, jma_node in enumerate(jma_file.nodes):
                            if 'pelvis' in jma_node.name:
                                pelvis = idx
                            if 'thigh' in jma_node.name:
                                if thigh0 == None:
                                    thigh0 = idx
                                else:
                                    thigh1 = idx

                            elif 'spine1' in jma_node.name:
                                spine1 = idx
                            elif 'clavicle' in jma_node.name:
                                if clavicle0 == None:
                                    clavicle0 = idx
                                else:
                                    clavicle1 = idx

                first_frame = jma_file.transforms[0]
                for idx, jma_node in enumerate(jma_file.nodes):
                    bpy.ops.object.mode_set(mode='EDIT')

                    armature.data.edit_bones.new(jma_node.name)
                    armature.data.edit_bones[jma_node.name].tail[2] = 5

                    parent_idx = jma_node.parent

                    if jms_a_transform:
                        if jma_node.name in jms_a_nodes:
                            node_idx = jms_a_nodes.index(jma_node.name)
                            rest_position = jms_a_file.transforms[0]
                            jms_node = rest_position[node_idx]

                        elif jma_node.name in jms_b_nodes:
                            node_idx = jms_b_nodes.index(jma_node.name)
                            rest_position = jms_b_file.transforms[0]
                            jms_node = rest_position[node_idx]

                        matrix_translate = Matrix.Translation(jms_node.vector)
                        matrix_scale = Matrix.Scale(1, 4, (1, 1, 1))
                        matrix_rotation = jms_node.rotation.to_matrix().to_4x4(
                        )
                    else:
                        matrix_translate = Matrix.Translation(
                            first_frame[idx].vector)
                        matrix_scale = Matrix.Scale(1, 4, (1, 1, 1))
                        matrix_rotation = first_frame[idx].rotation.to_matrix(
                        ).to_4x4()

                    if not parent_idx == -1 and not parent_idx == None:
                        parent = jma_file.nodes[parent_idx].name
                        if 'thigh' in jma_node.name and not pelvis == None and not thigh0 == None and not thigh1 == None:
                            parent = jma_file.nodes[pelvis].name
                        elif 'clavicle' in jma_node.name and not spine1 == None and not clavicle0 == None and not clavicle1 == None:
                            parent = jma_file.nodes[spine1].name

                        bpy.ops.object.mode_set(mode='EDIT')
                        armature.data.edit_bones[
                            jma_node.
                            name].parent = armature.data.edit_bones[parent]

                    bpy.ops.object.mode_set(mode='POSE')
                    pose_bone = armature.pose.bones[jma_node.name]
                    transform_matrix = matrix_translate @ matrix_rotation @ matrix_scale
                    primary_rest_positions = None
                    secondary_rest_positions = None
                    if jms_a_transform:
                        primary_rest_positions = jms_a_nodes[0]
                    if jms_b_transform:
                        secondary_rest_positions = jms_b_nodes[0]

                    if jma_file.version < 16394 and pose_bone.parent and not jma_node.name == primary_rest_positions and not jma_node.name == secondary_rest_positions:
                        transform_matrix = pose_bone.parent.matrix @ transform_matrix

                    armature.pose.bones[
                        jma_node.name].matrix = transform_matrix

                bpy.ops.pose.armature_apply(selected=False)

            else:
                report({
                    'ERROR'
                }, "No valid armature detected and not enough information to build valid skeleton due to version. Import will now be aborted"
                       )
                return {'CANCELLED'}

        else:
            report({
                'ERROR'
            }, "No valid armature detected and animation graph is invalid. Import will now be aborted"
                   )
            return {'CANCELLED'}

    scene.frame_end = jma_file.frame_count
    scene.render.fps = jma_file.frame_rate
    bpy.ops.object.mode_set(mode='POSE')

    nodes = jma_file.nodes
    if jma_file.version == 16390:
        nodes = global_functions.sort_by_layer(list(armature.data.bones),
                                               armature, False)

    for frame_idx, frame in enumerate(jma_file.transforms):
        scene.frame_set(frame_idx + 1)

        if jma_file.biped_controller_frame_type != JMAAsset.BipedControllerFrameType.DISABLE:
            controller_transform = jma_file.biped_controller_transforms[
                frame_idx]

            if jma_file.biped_controller_frame_type & JMAAsset.BipedControllerFrameType.DX:
                armature.location.x = controller_transform.vector[0]
            if jma_file.biped_controller_frame_type & JMAAsset.BipedControllerFrameType.DY:
                armature.location.y = controller_transform.vector[1]
            if jma_file.biped_controller_frame_type & JMAAsset.BipedControllerFrameType.DZ:
                armature.location.z = controller_transform.vector[2]

            if jma_file.biped_controller_frame_type & JMAAsset.BipedControllerFrameType.DYAW:
                armature.rotation_euler.z = controller_transform.rotation.to_euler(
                ).z

            armature.keyframe_insert('location')
            armature.keyframe_insert('rotation_euler')
            view_layer.update()

        for idx, node in enumerate(nodes):
            pose_bone = armature.pose.bones[node.name]

            matrix_scale = Matrix.Scale(frame[idx].scale, 4, (1, 1, 1))
            matrix_rotation = frame[idx].rotation.to_matrix().to_4x4()
            transform_matrix = Matrix.Translation(
                frame[idx].vector) @ matrix_rotation @ matrix_scale

            if jma_file.version < 16394 and pose_bone.parent:
                transform_matrix = pose_bone.parent.matrix @ transform_matrix

            pose_bone.matrix = transform_matrix
            view_layer.update()
            pose_bone.keyframe_insert('location')
            pose_bone.keyframe_insert('rotation_quaternion')
            pose_bone.keyframe_insert('scale')

    scene.frame_set(1)
    bpy.ops.object.mode_set(mode='OBJECT')
    report({'INFO'}, "Import completed successfully")
    return {'FINISHED'}
def transform_location(
    location: Vector, transform: Matrix = Matrix.Identity(4)) -> Vector:
    """Transform location."""
    m = Matrix.Translation(location)
    m = transform @ m
    return m.to_translation()
Esempio n. 18
0
def do_previews(do_objects, do_collections, do_scenes, do_data_intern):
    import collections

    # Helpers.
    RenderContext = collections.namedtuple("RenderContext", (
        "scene", "world", "camera", "light", "camera_data", "light_data", "image",  # All those are names!
        "backup_scene", "backup_world", "backup_camera", "backup_light", "backup_camera_data", "backup_light_data",
    ))

    RENDER_PREVIEW_SIZE = bpy.app.render_preview_size

    def render_context_create(engine, objects_ignored):
        if engine == '__SCENE':
            backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data = [()] * 6
            scene = bpy.context.window.scene
            exclude_props = {('world',), ('camera',), ('tool_settings',), ('preview',)}
            backup_scene = tuple(rna_backup_gen(scene, exclude_props=exclude_props))
            world = scene.world
            camera = scene.camera
            if camera:
                camera_data = camera.data
            else:
                backup_camera, backup_camera_data = [None] * 2
                camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
                camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
                camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ')  # (66.67, 0, 45)
                scene.camera = camera
                scene.collection.objects.link(camera)
            # TODO: add light if none found in scene?
            light = None
            light_data = None
        else:
            backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data = [None] * 6

            scene = bpy.data.scenes.new("TEMP_preview_render_scene")
            world = bpy.data.worlds.new("TEMP_preview_render_world")
            camera_data = bpy.data.cameras.new("TEMP_preview_render_camera")
            camera = bpy.data.objects.new("TEMP_preview_render_camera", camera_data)
            light_data = bpy.data.lights.new("TEMP_preview_render_light", 'SPOT')
            light = bpy.data.objects.new("TEMP_preview_render_light", light_data)

            objects_ignored.add((camera.name, light.name))

            scene.world = world

            camera.rotation_euler = Euler((1.1635528802871704, 0.0, 0.7853981852531433), 'XYZ')  # (66.67, 0, 45)
            scene.camera = camera
            scene.collection.objects.link(camera)

            light.rotation_euler = Euler((0.7853981852531433, 0.0, 1.7453292608261108), 'XYZ')  # (45, 0, 100)
            light_data.falloff_type = 'CONSTANT'
            light_data.spot_size = 1.0471975803375244  # 60
            scene.collection.objects.link(light)

            scene.render.engine = 'CYCLES'
            scene.render.film_transparent = True
            # TODO: define Cycles world?

        scene.render.image_settings.file_format = 'PNG'
        scene.render.image_settings.color_depth = '8'
        scene.render.image_settings.color_mode = 'RGBA'
        scene.render.image_settings.compression = 25
        scene.render.resolution_x = RENDER_PREVIEW_SIZE
        scene.render.resolution_y = RENDER_PREVIEW_SIZE
        scene.render.resolution_percentage = 100
        scene.render.filepath = os.path.join(bpy.app.tempdir, 'TEMP_preview_render.png')
        scene.render.use_overwrite = True
        scene.render.use_stamp = False
        scene.render.threads_mode = 'AUTO'

        image = bpy.data.images.new("TEMP_render_image", RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE, alpha=True)
        image.source = 'FILE'
        image.filepath = scene.render.filepath

        return RenderContext(
            scene.name, world.name if world else None, camera.name, light.name if light else None,
            camera_data.name, light_data.name if light_data else None, image.name,
            backup_scene, backup_world, backup_camera, backup_light, backup_camera_data, backup_light_data,
        )

    def render_context_delete(render_context):
        # We use try/except blocks here to avoid crash, too much things can go wrong, and we want to leave the current
        # .blend as clean as possible!
        success = True

        scene = bpy.data.scenes[render_context.scene, None]
        try:
            if render_context.backup_scene is None:
                scene.world = None
                scene.camera = None
                if render_context.camera:
                    scene.collection.objects.unlink(bpy.data.objects[render_context.camera, None])
                if render_context.light:
                    scene.collection.objects.unlink(bpy.data.objects[render_context.light, None])
                bpy.data.scenes.remove(scene, do_unlink=True)
                scene = None
            else:
                rna_backup_restore(scene, render_context.backup_scene)
        except Exception as e:
            print("ERROR:", e)
            success = False

        if render_context.world is not None:
            try:
                world = bpy.data.worlds[render_context.world, None]
                if render_context.backup_world is None:
                    if scene is not None:
                        scene.world = None
                    world.user_clear()
                    bpy.data.worlds.remove(world)
                else:
                    rna_backup_restore(world, render_context.backup_world)
            except Exception as e:
                print("ERROR:", e)
                success = False

        if render_context.camera:
            try:
                camera = bpy.data.objects[render_context.camera, None]
                if render_context.backup_camera is None:
                    if scene is not None:
                        scene.camera = None
                        scene.collection.objects.unlink(camera)
                    camera.user_clear()
                    bpy.data.objects.remove(camera)
                    bpy.data.cameras.remove(bpy.data.cameras[render_context.camera_data, None])
                else:
                    rna_backup_restore(camera, render_context.backup_camera)
                    rna_backup_restore(bpy.data.cameras[render_context.camera_data, None],
                                       render_context.backup_camera_data)
            except Exception as e:
                print("ERROR:", e)
                success = False

        if render_context.light:
            try:
                light = bpy.data.objects[render_context.light, None]
                if render_context.backup_light is None:
                    if scene is not None:
                        scene.collection.objects.unlink(light)
                    light.user_clear()
                    bpy.data.objects.remove(light)
                    bpy.data.lights.remove(bpy.data.lights[render_context.light_data, None])
                else:
                    rna_backup_restore(light, render_context.backup_light)
                    rna_backup_restore(bpy.data.lights[render_context.light_data,
                                                       None], render_context.backup_light_data)
            except Exception as e:
                print("ERROR:", e)
                success = False

        try:
            image = bpy.data.images[render_context.image, None]
            image.user_clear()
            bpy.data.images.remove(image)
        except Exception as e:
            print("ERROR:", e)
            success = False

        return success

    def object_bbox_merge(bbox, ob, ob_space, offset_matrix):
        # Take collections instances into account (including linked one in this case).
        if ob.type == 'EMPTY' and ob.instance_type == 'COLLECTION':
            grp_objects = tuple((ob.name, ob.library.filepath if ob.library else None)
                                for ob in ob.instance_collection.all_objects)
            if (len(grp_objects) == 0):
                ob_bbox = ob.bound_box
            else:
                coords = objects_bbox_calc(ob_space, grp_objects,
                                           Matrix.Translation(ob.instance_collection.instance_offset).inverted())
                ob_bbox = ((coords[0], coords[1], coords[2]), (coords[21], coords[22], coords[23]))
        elif ob.bound_box:
            ob_bbox = ob.bound_box
        else:
            ob_bbox = ((-ob.scale.x, -ob.scale.y, -ob.scale.z), (ob.scale.x, ob.scale.y, ob.scale.z))

        for v in ob_bbox:
            v = offset_matrix @ Vector(v) if offset_matrix is not None else Vector(v)
            v = ob_space.matrix_world.inverted() @ ob.matrix_world @ v
            if bbox[0].x > v.x:
                bbox[0].x = v.x
            if bbox[0].y > v.y:
                bbox[0].y = v.y
            if bbox[0].z > v.z:
                bbox[0].z = v.z
            if bbox[1].x < v.x:
                bbox[1].x = v.x
            if bbox[1].y < v.y:
                bbox[1].y = v.y
            if bbox[1].z < v.z:
                bbox[1].z = v.z

    def objects_bbox_calc(camera, objects, offset_matrix):
        bbox = (Vector((1e24, 1e24, 1e24)), Vector((-1e24, -1e24, -1e24)))
        for obname, libpath in objects:
            ob = bpy.data.objects[obname, libpath]
            object_bbox_merge(bbox, ob, camera, offset_matrix)
        # Our bbox has been generated in camera local space, bring it back in world one
        bbox[0][:] = camera.matrix_world @ bbox[0]
        bbox[1][:] = camera.matrix_world @ bbox[1]
        cos = (
            bbox[0].x, bbox[0].y, bbox[0].z,
            bbox[0].x, bbox[0].y, bbox[1].z,
            bbox[0].x, bbox[1].y, bbox[0].z,
            bbox[0].x, bbox[1].y, bbox[1].z,
            bbox[1].x, bbox[0].y, bbox[0].z,
            bbox[1].x, bbox[0].y, bbox[1].z,
            bbox[1].x, bbox[1].y, bbox[0].z,
            bbox[1].x, bbox[1].y, bbox[1].z,
        )
        return cos

    def preview_render_do(render_context, item_container, item_name, objects, offset_matrix=None):
        # Unused.
        # scene = bpy.data.scenes[render_context.scene, None]
        if objects is not None:
            camera = bpy.data.objects[render_context.camera, None]
            light = bpy.data.objects[render_context.light, None] if render_context.light is not None else None
            cos = objects_bbox_calc(camera, objects, offset_matrix)
            depsgraph = bpy.context.evaluated_depsgraph_get()
            loc, _ortho_scale = camera.camera_fit_coords(depsgraph, cos)
            camera.location = loc
            # Set camera clipping accordingly to computed bbox.
            min_dist = 1e24
            max_dist = -1e24
            for co in zip(*(iter(cos),) * 3):
                dist = (Vector(co) - loc).length
                if dist < min_dist:
                    min_dist = dist
                if dist > max_dist:
                    max_dist = dist
            camera.data.clip_start = min_dist / 2
            camera.data.clip_end = max_dist * 2
            if light:
                loc, _ortho_scale = light.camera_fit_coords(depsgraph, cos)
                light.location = loc
        bpy.context.view_layer.update()

        bpy.ops.render.render(write_still=True)

        image = bpy.data.images[render_context.image, None]
        item = getattr(bpy.data, item_container)[item_name, None]
        image.reload()
        preview = item.preview_ensure()
        preview.image_size = (RENDER_PREVIEW_SIZE, RENDER_PREVIEW_SIZE)
        preview.image_pixels_float[:] = image.pixels

    # And now, main code!
    do_save = True

    if do_data_intern:
        bpy.ops.wm.previews_clear(id_type={'SHADING'})
        bpy.ops.wm.previews_ensure()

    render_contexts = {}

    objects_ignored = set()
    collections_ignored = set()

    prev_scenename = bpy.context.window.scene.name

    if do_objects:
        prev_shown = {ob.name: ob.hide_render for ob in ids_nolib(bpy.data.objects)}
        for ob in ids_nolib(bpy.data.objects):
            if ob in objects_ignored:
                continue
            ob.hide_render = True
        for root in ids_nolib(bpy.data.objects):
            if root.name in objects_ignored:
                continue
            if root.type not in OBJECT_TYPES_RENDER:
                continue
            objects = ((root.name, None),)

            render_context = render_contexts.get('CYCLES', None)
            if render_context is None:
                render_context = render_context_create('CYCLES', objects_ignored)
                render_contexts['CYCLES'] = render_context

            scene = bpy.data.scenes[render_context.scene, None]
            bpy.context.window.scene = scene

            for obname, libpath in objects:
                ob = bpy.data.objects[obname, libpath]
                if obname not in scene.objects:
                    scene.collection.objects.link(ob)
                ob.hide_render = False
            bpy.context.view_layer.update()

            preview_render_do(render_context, 'objects', root.name, objects)

            # XXX Hyper Super Uber Suspicious Hack!
            #     Without this, on windows build, script excepts with following message:
            #         Traceback (most recent call last):
            #         File "<string>", line 1, in <module>
            #         File "<string>", line 451, in <module>
            #         File "<string>", line 443, in main
            #         File "<string>", line 327, in do_previews
            #         OverflowError: Python int too large to convert to C long
            #    ... :(
            scene = bpy.data.scenes[render_context.scene, None]
            for obname, libpath in objects:
                ob = bpy.data.objects[obname, libpath]
                scene.collection.objects.unlink(ob)
                ob.hide_render = True

        for ob in ids_nolib(bpy.data.objects):
            is_rendered = prev_shown.get(ob.name, ...)
            if is_rendered is not ...:
                ob.hide_render = is_rendered

    if do_collections:
        for grp in ids_nolib(bpy.data.collections):
            if grp.name in collections_ignored:
                continue
            # Here too, we do want to keep linked objects members of local collection...
            objects = tuple((ob.name, ob.library.filepath if ob.library else None) for ob in grp.objects)

            render_context = render_contexts.get('CYCLES', None)
            if render_context is None:
                render_context = render_context_create('CYCLES', objects_ignored)
                render_contexts['CYCLES'] = render_context

            scene = bpy.data.scenes[render_context.scene, None]
            bpy.context.window.scene = scene

            bpy.ops.object.collection_instance_add(collection=grp.name)
            grp_ob = next((
                ob for ob in scene.objects
                if ob.instance_collection and ob.instance_collection.name == grp.name
            ))
            grp_obname = grp_ob.name
            bpy.context.view_layer.update()

            offset_matrix = Matrix.Translation(grp.instance_offset).inverted()

            preview_render_do(render_context, 'collections', grp.name, objects, offset_matrix)

            scene = bpy.data.scenes[render_context.scene, None]
            scene.collection.objects.unlink(bpy.data.objects[grp_obname, None])

    bpy.context.window.scene = bpy.data.scenes[prev_scenename, None]
    for render_context in render_contexts.values():
        if not render_context_delete(render_context):
            do_save = False  # Do not save file if something went wrong here, we could 'pollute' it with temp data...

    if do_scenes:
        for scene in ids_nolib(bpy.data.scenes):
            has_camera = scene.camera is not None
            bpy.context.window.scene = scene
            render_context = render_context_create('__SCENE', objects_ignored)
            bpy.context.view_layer.update()

            objects = None
            if not has_camera:
                # We had to add a temp camera, now we need to place it to see interesting objects!
                objects = tuple((ob.name, ob.library.filepath if ob.library else None) for ob in scene.objects
                                if (not ob.hide_render) and (ob.type in OBJECT_TYPES_RENDER))

            preview_render_do(render_context, 'scenes', scene.name, objects)

            if not render_context_delete(render_context):
                do_save = False

    bpy.context.window.scene = bpy.data.scenes[prev_scenename, None]
    if do_save:
        print("Saving %s..." % bpy.data.filepath)
        try:
            bpy.ops.wm.save_mainfile()
        except Exception as e:
            # Might fail in some odd cases, like e.g. in regression files we have glsl/ram_glsl.blend which
            # references an inexistent texture... Better not break in this case, just spit error to console.
            print("ERROR:", e)
    else:
        print("*NOT* Saving %s, because some error(s) happened while deleting temp render data..." % bpy.data.filepath)
Esempio n. 19
0
    def align_to_active(self, active, sel):
        # get target matrix and decompose
        amx = active.matrix_world
        aloc, arot, asca = amx.decompose()

        # split components into x,y,z axis elements
        alocx, alocy, alocz = aloc
        arotx, aroty, arotz = arot.to_euler('XYZ')
        ascax, ascay, ascaz = asca

        for obj in sel:
            # get object matrix and decompose
            omx = obj.matrix_world
            oloc, orot, osca = omx.decompose()

            # split components into x,y,z axis elements
            olocx, olocy, olocz = oloc
            orotx, oroty, orotz = orot.to_euler('XYZ')
            oscax, oscay, oscaz = osca

            # TRANSLATION

            # if location is aligned, pick the axis elements based on the loc axis props
            if self.location:
                locx = alocx if self.loc_x else olocx
                locy = alocy if self.loc_y else olocy
                locz = alocz if self.loc_z else olocz

                # re-assemble into translation matrix
                loc = Matrix.Translation(Vector((locx, locy, locz)))

            # otherwise, just use the object's location component
            else:
                loc = Matrix.Translation(oloc)

            # ROTATION

            # if rotation is aligned, pick the axis elements based on the rot axis props
            if self.rotation:
                rotx = arotx if self.rot_x else orotx
                roty = aroty if self.rot_y else oroty
                rotz = arotz if self.rot_z else orotz

                # re-assemble into rotation matrix
                rot = Euler((rotx, roty, rotz), 'XYZ').to_matrix().to_4x4()

            # otherwise, just use the object's rotation component
            else:
                rot = orot.to_matrix().to_4x4()

            # SCALE

            sca = Matrix()

            # if scale is aligned, pick the axis elements based on the sca axis props
            if self.scale:
                scax = ascax if self.sca_x else oscax
                scay = ascay if self.sca_y else oscay
                scaz = ascaz if self.sca_z else oscaz

                # re-assemble into scale matrix
                for i in range(3):
                    sca[i][i] = (scax, scay, scaz)[i]

            # otherwise, just use the object's scale component
            else:
                for i in range(3):
                    sca[i][i] = osca[i]

            # re-combine components into world matrix
            obj.matrix_world = loc @ rot @ sca
Esempio n. 20
0
    def build_objects(props, grid) -> None:
        mesh_cells = props.objects.cells.data
        mesh_walls = props.objects.walls.data

        cells_corners, cells_faces, stairs_vertex_group, walls_edges = MeshManager.get_mesh_info(
            grid, props.cell_inset, props.path.force_outside)

        mesh_cells.clear_geometry()
        mesh_cells.from_pydata(cells_corners, [], cells_faces)
        mesh_walls.clear_geometry()
        mesh_walls.from_pydata(cells_corners, walls_edges, [])

        bm_cells = bmesh.new()
        bm_cells.from_mesh(mesh_cells)

        bm_walls = bmesh.new()
        bm_walls.from_mesh(mesh_walls)

        distance_vc = bm_cells.loops.layers.color.new(DISTANCE)
        group_vc = bm_cells.loops.layers.color.new(GROUP)
        neighbors_vc = bm_cells.loops.layers.color.new(NEIGHBORS)
        vg_cells = bm_cells.verts.layers.deform.new()
        vg_walls = bm_walls.verts.layers.deform.new()

        random.seed(props.seed_color)

        groups = grid.groups
        group_colors = {}
        max_groups = max(max(grid.groups), 1)
        for g in groups:
            val = g / max_groups
            group_colors[g] = val, val, val, 1

        max_neighbors = max(grid.max_links_per_cell, 1)
        neighbors_colors = {}
        for n in range(max_neighbors + 1):
            val = n / max_neighbors
            neighbors_colors[n] = val, val, val, 1

        bm_cells.verts.ensure_lookup_table()
        bm_walls.verts.ensure_lookup_table()
        for vg_info, weights in stairs_vertex_group.items():
            for v_ind in vg_info:
                bm_cells_vert = bm_cells.verts[v_ind]
                bm_cells_vert[vg_cells][0] = weights[0]
                bm_cells_vert[vg_cells][2] = weights[1]

                bm_walls_vert = bm_walls.verts[v_ind]
                bm_walls_vert[vg_walls][0] = weights[0]
                bm_walls_vert[vg_walls][1] = 1
                bm_walls_vert[vg_walls][2] = weights[1]

                for loop in bm_cells_vert.link_loops:
                    loop[distance_vc] = (weights[0], weights[1], 0, 0)
                    loop[group_vc] = group_colors[weights[2]]
                    loop[neighbors_vc] = neighbors_colors[weights[3]]

        bm_cells.to_mesh(mesh_cells)
        bm_walls.to_mesh(mesh_walls)

        mesh_cells.transform(Matrix.Translation(grid.offset))
        mesh_walls.transform(Matrix.Translation(grid.offset))

        if props.cell_use_smooth:  # Update only when the mesh is supposed to be smoothed, because the default will be unsmoothed
            MeshManager.update_smooth(props)
        for mesh in (mesh_cells, mesh_walls):
            mesh.use_auto_smooth = True
            mesh.auto_smooth_angle = 0.5
Esempio n. 21
0
 def calc_target_view_matrix(self, start_target, end_target, factor):
     return Matrix.Translation(Vector((0, 0, 5)))
Esempio n. 22
0
def get_loc_matrix(location):
    return Matrix.Translation(location)
Esempio n. 23
0
 def get_object_matrix(self):
     bound_center = self.calc_bounding_box_center()
     return self.object.matrix_world * Matrix.Translation(bound_center)
 def make_name_plate_notches(self):
     self.remove_name_plate()
     x = [
         self.location[0] - (0.5 * self.Size_x),
         self.location[0] + (0.5 * self.Size_x),
         self.location[0] + (0.25 * self.Size_x) - 1.75,
         self.location[0] + (0.25 * self.Size_x) + 1.75,
         self.location[0] + (0.25 * self.Size_x) - 3.5,
         self.location[0] + (0.25 * self.Size_x) + 3.5,
         self.location[0] - (0.25 * self.Size_x) - 1.75,
         self.location[0] - (0.25 * self.Size_x) + 1.75,
         self.location[0] - (0.25 * self.Size_x) - 3.5,
         self.location[0] - (0.25 * self.Size_x) + 3.5
     ]
     y = [
         self.location[1] + (0.5 * self.Size_y),
         self.location[1] - (0.5 * self.Size_y), self.location[1] +
         (0.5 * self.Size_y) - (self.Border_width * 2 / 3)
     ]
     z = [
         self.location[2] + (0.5 * self.Size_z),
         self.location[2] - (0.5 * self.Size_z),
         self.location[2] - (0.5 * self.Size_z) + self.Base_height
     ]
     verts = [
         Vector((x[0], y[0], z[0])),
         Vector((x[1], y[0], z[0])),
         Vector((x[1], y[1], z[0])),
         Vector((x[0], y[1], z[0])),
         Vector((x[0], y[0], z[1])),
         Vector((x[1], y[0], z[1])),
         Vector((x[1], y[1], z[1])),
         Vector((x[0], y[1], z[1])),
         Vector((x[2], y[0], z[1])),
         Vector((x[3], y[0], z[1])),
         Vector((x[3], y[2], z[1])),
         Vector((x[2], y[2], z[1])),
         Vector((x[4], y[0], z[2])),
         Vector((x[5], y[0], z[2])),
         Vector((x[5], y[2], z[2])),
         Vector((x[4], y[2], z[2])),
         Vector((x[6], y[0], z[1])),
         Vector((x[7], y[0], z[1])),
         Vector((x[7], y[2], z[1])),
         Vector((x[6], y[2], z[1])),
         Vector((x[8], y[0], z[2])),
         Vector((x[9], y[0], z[2])),
         Vector((x[9], y[2], z[2])),
         Vector((x[8], y[2], z[2])),
     ]
     faces = [(3, 2, 1, 0), (4, 7, 3, 0), (1, 2, 6, 5), (7, 6, 2, 3),
              (12, 13, 14, 15), (9, 10, 14, 13), (12, 15, 11, 8),
              (15, 14, 10, 11), (20, 21, 22, 23), (17, 18, 22, 21),
              (20, 23, 19, 16), (23, 22, 18, 19),
              (4, 16, 19, 18, 17, 8, 11, 10, 9, 5, 6, 7),
              (0, 1, 5, 9, 13, 12, 8, 17, 21, 20, 16, 4)]
     me = bpy.data.meshes.new(self.name_plate_mesh_key)
     self.name_plate = bpy.data.objects.new(self.name_plate_object_key, me)
     bpy.context.scene.objects.link(self.name_plate)
     me.from_pydata(verts, [], faces)
     me.update()
     bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
     R = Matrix.Rotation(math.radians(180), 4, Vector((0, 0, 1)))
     T = Matrix.Translation(self.location)
     TRT = T * R * T.inverted()
     self.name_plate.location = TRT * self.name_plate.location
     self.name_plate.rotation_euler.rotate(TRT)
def setCharacterPosition(charObject, source, sourceSplinePosition,
                         offsetPosition):
    characterOffset = sourceSplinePosition - offsetPosition
    charObject.matrix_world = source.matrix_world * Matrix.Translation(
        characterOffset)
Esempio n. 26
0
def _create_blender_armature_from_mod(mod, armature_name, parent=None):
    armature = bpy.data.armatures.new(armature_name)
    armature_ob = bpy.data.objects.new(armature_name, armature)
    armature_ob.parent = parent
    bpy.context.scene.objects.link(armature_ob)

    if bpy.context.mode != 'OBJECT':
        bpy.ops.object.mode_set(mode='OBJECT')
    # deselect all objects
    for i in bpy.context.scene.objects:
        i.select = False
    bpy.context.scene.objects.active = armature_ob
    armature_ob.select = True
    bpy.ops.object.mode_set(mode='EDIT')

    blender_bones = []
    for i, bone in enumerate(mod.bones_array):
        blender_bone = armature.edit_bones.new(str(i))
        blender_bones.append(blender_bone)
        parents = get_bone_parents_from_mod(bone, mod.bones_array)
        if not parents:
            blender_bone.head = Vector(
                (bone.location_x / 100, bone.location_z * -1 / 100,
                 bone.location_y / 100))
            continue
        chain = [i] + parents
        wtm = Matrix.Translation((0, 0, 0))
        for bi in reversed(chain):
            b = mod.bones_array[bi]
            wtm *= Matrix.Translation(
                (b.location_x / 100, b.location_z / 100 * -1,
                 b.location_y / 100))
        blender_bone.head = wtm.to_translation()
        blender_bone.parent = blender_bones[bone.parent_index]

    assert len(blender_bones) == len(mod.bones_array)

    # set tails of bone to their children or make them small if they have none
    for i, bone in enumerate(blender_bones):
        children = bone.children_recursive
        non_mirror_children = [
            b for b in children
            if mod.bones_array[int(b.name)].mirror_index == int(b.name)
        ]
        mirror_children = [
            b for b in children
            if mod.bones_array[int(b.name)].mirror_index != int(b.name)
        ]
        if mod.bones_array[i].mirror_index == i and non_mirror_children:
            bone.tail = non_mirror_children[0].head
        elif mod.bones_array[i].mirror_index != i and mirror_children:
            bone.tail = mirror_children[0].head
        else:
            bone.length = 0.01
        # Some very small numbers won't be equal without rounding, but blender will
        # later treat them as equal, so using rounding here
        if round(bone.tail[0], 10) == round(bone.head[0], 10):
            bone.tail[0] += 0.01
        if round(bone.tail[1], 10) == round(bone.head[1], 10):
            bone.tail[1] += 0.01
        if round(bone.tail[2], 10) == round(bone.head[2], 10):
            bone.tail[2] += 0.01

    bpy.ops.object.mode_set(mode='OBJECT')
    assert len(armature.bones) == len(mod.bones_array)
    return armature_ob
Esempio n. 27
0
    def test_obj_and_cam_blur(self):
        """
        One object ("moving_obj") and the camera ("moving_camera") are moving.
        Camera and object motion blur are enabled.
        """
        blender_scene = bpy.context.scene

        # Switch to the moving camera
        blender_scene.camera = bpy.data.objects["moving_camera"]

        # Switch to correct frame in case someone messed it up on save
        blender_scene.frame_set(TEST_FRAME, TEST_SUBFRAME)

        # Get the object that moves and should be blurred
        moving_obj = bpy.data.objects["moving_obj"]
        moving_obj_name = utils.get_luxcore_name(moving_obj,
                                                 is_viewport_render=False)

        # Make sure the settings are correct
        # (can only change if someone messes with the test scene)
        self.assertIsNotNone(blender_scene.camera)
        blur_settings = blender_scene.camera.data.luxcore.motion_blur
        self.assertTrue(blur_settings.enable)
        self.assertAlmostEqual(blur_settings.shutter, 4.0)
        self.assertTrue(blur_settings.object_blur)
        self.assertTrue(blur_settings.camera_blur)
        self.assertEqual(blur_settings.steps, 2)
        # Make sure we are at the correct frame
        self.assertEqual(blender_scene.frame_current, 3)
        self.assertAlmostEqual(blender_scene.frame_subframe, 0.0)

        # Export the scene
        scene_props = export(blender_scene)

        # Check properties for correctness
        all_exported_obj_prefixes = scene_props.GetAllUniqueSubNames(
            "scene.objects")

        for prefix in all_exported_obj_prefixes:
            luxcore_name = prefix.split(".")[-1]

            if luxcore_name == moving_obj_name:
                test_moving_object(self, scene_props, prefix)

        # Check if camera shutter settings are correct
        # Total shutter duration is 4.0 frames, so these should be -2.0 and 2.0
        self.assertAlmostEqual(
            scene_props.Get("scene.camera.shutteropen").GetFloat(), -2.0)
        self.assertAlmostEqual(
            scene_props.Get("scene.camera.shutterclose").GetFloat(), 2.0)

        # Check if camera transformation props are correct

        # Test the times
        # step 0. Shutter is 4.0 frames, so this step should be minus half of the shutter value
        self.assertAlmostEqual(
            scene_props.Get("scene.camera.motion.0.time").GetFloat(), -2.0)
        # step 1. This should be half of the shutter value
        self.assertAlmostEqual(
            scene_props.Get("scene.camera.motion.1.time").GetFloat(), 2.0)

        # Test the transformation matrices

        # step 0. We are at X = 3m, Y = 0, Z = 0m
        translation = Matrix.Translation([3, 0, 0])
        rotation = Matrix.Rotation(math.radians(-90.0), 4, "X")
        scale = Matrix.Scale(1, 4)
        expected_step_0 = create_expected_matrix(blender_scene, translation,
                                                 rotation, scale)
        # For some reason we need to invert these two... my matrix math is rusty
        expected_step_0[6] *= -1
        expected_step_0[9] *= -1

        transformation_step_0 = scene_props.Get(
            "scene.camera.motion.0.transformation").GetFloats()
        assertListsAlmostEqual(self, transformation_step_0, expected_step_0)

        # step 1. We are at X = -3m, Y = 0, Z = 0m
        translation = Matrix.Translation([-3, 0, 0])
        rotation = Matrix.Rotation(math.radians(-90.0), 4, "X")
        scale = Matrix.Scale(1, 4)
        expected_step_1 = create_expected_matrix(blender_scene, translation,
                                                 rotation, scale)
        # For some reason we need to invert these two... my matrix math is rusty
        expected_step_1[6] *= -1
        expected_step_1[9] *= -1

        transformation_step_1 = scene_props.Get(
            "scene.camera.motion.1.transformation").GetFloats()
        assertListsAlmostEqual(self, transformation_step_1, expected_step_1)
Esempio n. 28
0
    def execute(self, context):
        import collections
        import operator
        import itertools

        rotvar = self.rot_var - 1
        yvar = self.y_var - 1
        app = self.mats.append

        bpy.ops.mesh.separate(type="LOOSE")
        bpy.ops.object.origin_set(type="ORIGIN_GEOMETRY", center="MEDIAN")

        for ob in context.selected_objects:
            normal_groups = collections.defaultdict(float)

            for poly in ob.data.polygons:
                normal_groups[poly.normal.copy().freeze()] += poly.area

            normals = sorted(normal_groups.items(), key=operator.itemgetter(1), reverse=True)

            try:
                normal = normals[rotvar][0]
            except IndexError:
                normal = normals[0][0]

            mat = normal.to_track_quat("Z", "Y").to_matrix().to_4x4()
            ob.matrix_world @= mat
            ob.data.transform(mat.inverted())

            # Adjust origin
            # ------------------------------

            verts = sorted(ob.data.vertices, key=operator.attrgetter("co.xy.length"), reverse=True)[:8]

            # Z height

            co_z_low = min(verts, key=operator.attrgetter("co.z")).co.z

            if co_z_low != 0.0:
                mat = Matrix.Translation((0.0, 0.0, co_z_low))
                ob.matrix_world @= mat
                ob.data.transform(mat.inverted())

            # Y align

            if self.y_align:

                if self.snap_to_edge:
                    cos = [
                        (
                            (v1.co.xy + v2.co.xy) / 2,
                            (v1.co.xy - v2.co.xy).length,
                        )
                        for v1, v2 in itertools.combinations(verts, 2)
                    ]
                    cos.sort(key=operator.itemgetter(1))

                    try:
                        vec = cos[yvar][0]
                    except IndexError:
                        vec = cos[0][0]

                else:
                    try:
                        vec = verts[yvar].co.xy
                    except IndexError:
                        vec = verts[0].co.xy

                vec.negate()
                vec.resize_3d()

                mat = vec.to_track_quat("Y", "Z").to_matrix().to_4x4()
                ob.matrix_world @= mat
                ob.data.transform(mat.inverted())

            # XY center

            if self.xy_loc != 0:

                if self.xy_loc == 1:
                    context.view_layer.update()

                    xy_min = min((x[0], x[1]) for x in ob.bound_box)
                    xy_max = max((x[0], x[1]) for x in ob.bound_box)

                    x_loc = (xy_min[0] + xy_max[0]) / 2
                    y_loc = (xy_min[1] + xy_max[1]) / 2

                    co_xy = (x_loc, y_loc)

                elif self.xy_loc == 2:
                    co_xy = min(ob.data.vertices, key=operator.attrgetter("co.z")).co.xy

                if co_xy[0] != 0.0 or co_xy[1] != 0.0:
                    mat = Matrix.Translation((*co_xy, 0.0))
                    ob.matrix_world @= mat
                    ob.data.transform(mat.inverted())

            # Display axis

            app(ob.matrix_world.copy())

        return {"FINISHED"}
    def glsl_draw(self):
        if GlslDrawObj.myinstance is None and GlslDrawObj.draw_func is None:
            glsl_draw_obj = GlslDrawObj()
            glsl_draw_obj.build_scene()
        else:
            glsl_draw_obj = GlslDrawObj.myinstance
        model_offset = Matrix.Translation((glsl_draw_obj.draw_x_offset, 0, 0))
        light_pos = [
            i + n for i, n in zip(glsl_draw_obj.light.location,
                                  [-glsl_draw_obj.draw_x_offset, 0, 0])
        ]
        batches = glsl_draw_obj.batches
        depth_shader = glsl_draw_obj.depth_shader
        toon_shader = glsl_draw_obj.toon_shader
        offscreen = glsl_draw_obj.offscreen
        # need bone etc changed only update
        depth_matrix = None

        light = glsl_draw_obj.light
        light_lookat = light.rotation_euler.to_quaternion() @ Vector(
            (0, 0, -1))
        # TODO このへん
        tar = light_lookat.normalized()
        up = light.rotation_euler.to_quaternion() @ Vector((0, 1, 0))
        tmp_bound_len = Vector(glsl_draw_obj.bounding_center).length
        camera_bias = 0.2
        loc = Vector([
            glsl_draw_obj.bounding_center[i] + tar[i] *
            (tmp_bound_len + camera_bias) for i in range(3)
        ])

        loc = model_offset @ loc
        v_matrix = lookat_cross(loc, tar, up)
        const_proj = 2 * max(glsl_draw_obj.bounding_size) / 2
        p_matrix = ortho_proj_mat(-const_proj, const_proj, -const_proj,
                                  const_proj, -const_proj, const_proj)
        depth_matrix = v_matrix @ p_matrix  # reuse in main shader
        depth_matrix.transpose()

        # region shader depth path
        with offscreen.bind():
            bgl.glClearColor(10, 10, 10, 1)
            bgl.glClear(bgl.GL_COLOR_BUFFER_BIT | bgl.GL_DEPTH_BUFFER_BIT)
            for bat in batches:
                mat = bat[0]
                mat.update()
                depth_bat = bat[2]
                depth_shader.bind()

                bgl.glEnable(bgl.GL_BLEND)
                if mat.alpha_method == "TRANSPARENT":
                    bgl.glBlendFunc(bgl.GL_SRC_ALPHA,
                                    bgl.GL_ONE_MINUS_SRC_ALPHA)
                    bgl.glDepthMask(bgl.GL_TRUE)
                    bgl.glEnable(bgl.GL_DEPTH_TEST)
                elif mat.alpha_method == "OPAQUE":
                    bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO)
                    bgl.glDepthMask(bgl.GL_TRUE)
                    bgl.glEnable(bgl.GL_DEPTH_TEST)
                elif mat.alpha_method == "CLIP":
                    bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO)
                    bgl.glDepthMask(bgl.GL_TRUE)
                    bgl.glEnable(bgl.GL_DEPTH_TEST)

                if mat.cull_mode == "BACK":
                    bgl.glEnable(bgl.GL_CULL_FACE)
                    bgl.glCullFace(bgl.GL_BACK)
                else:
                    bgl.glDisable(bgl.GL_CULL_FACE)
                bgl.glEnable(bgl.GL_CULL_FACE)  # そも輪郭線がの影は落ちる?
                bgl.glCullFace(bgl.GL_BACK)

                depth_shader.uniform_float("obj_matrix",
                                           model_offset)  # obj.matrix_world)
                depth_shader.uniform_float("depthMVP", depth_matrix)

                depth_bat.draw(depth_shader)
        # endregion shader depth path

        # region shader main
        vp_mat = bpy.context.region_data.perspective_matrix
        projection_mat = bpy.context.region_data.window_matrix
        view_dir = bpy.context.region_data.view_matrix[2][:3]
        view_up = bpy.context.region_data.view_matrix[1][:3]
        normal_world_to_view_matrix = (
            bpy.context.region_data.view_matrix.inverted_safe().transposed())
        aspect = bpy.context.area.width / bpy.context.area.height

        for is_outline in [0, 1]:
            for bat in batches:

                toon_bat = bat[1]
                toon_shader.bind()
                mat = bat[0]

                if is_outline == 1 and mat.float_dic["OutlineWidthMode"] == 0:
                    continue
                # mat.update() #already in depth path
                bgl.glEnable(bgl.GL_BLEND)
                bgl.glDepthMask(bgl.GL_TRUE)
                bgl.glEnable(bgl.GL_DEPTH_TEST)
                if mat.alpha_method == "TRANSPARENT":
                    bgl.glBlendFunc(bgl.GL_SRC_ALPHA,
                                    bgl.GL_ONE_MINUS_SRC_ALPHA)
                elif mat.alpha_method == "OPAQUE":
                    bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO)
                elif mat.alpha_method == "CLIP":
                    bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ZERO)

                if is_outline == 0:
                    if mat.cull_mode == "BACK":
                        bgl.glEnable(bgl.GL_CULL_FACE)
                        bgl.glCullFace(bgl.GL_BACK)
                    else:
                        bgl.glDisable(bgl.GL_CULL_FACE)
                else:
                    bgl.glEnable(bgl.GL_CULL_FACE)
                    bgl.glCullFace(bgl.GL_BACK)

                toon_shader.uniform_float("obj_matrix",
                                          model_offset)  # obj.matrix_world)
                toon_shader.uniform_float("projectionMatrix", projection_mat)
                toon_shader.uniform_float("viewProjectionMatrix", vp_mat)
                toon_shader.uniform_float("viewDirection", view_dir)
                toon_shader.uniform_float("viewUpDirection", view_up)
                toon_shader.uniform_float("normalWorldToViewMatrix",
                                          normal_world_to_view_matrix)
                toon_shader.uniform_float("depthMVP", depth_matrix)
                toon_shader.uniform_float("lightpos", light_pos)
                toon_shader.uniform_float("aspect", aspect)
                toon_shader.uniform_float("is_outline", is_outline)
                toon_shader.uniform_float("isDebug", 0.0)

                toon_shader.uniform_float(
                    "is_cutout", 1.0 if mat.alpha_method == "CLIP" else 0.0)

                float_keys = [
                    "CutoffRate",
                    "BumpScale",
                    "ReceiveShadowRate",
                    "ShadeShift",
                    "ShadeToony",
                    "RimLightingMix",
                    "RimFresnelPower",
                    "RimLift",
                    "ShadingGradeRate",
                    "LightColorAttenuation",
                    "IndirectLightIntensity",
                    "OutlineWidth",
                    "OutlineScaleMaxDistance",
                    "OutlineLightingMix",
                    "UV_Scroll_X",
                    "UV_Scroll_Y",
                    "UV_Scroll_Rotation",
                    "OutlineWidthMode",
                    "OutlineColorMode",
                ]

                for k in float_keys:
                    toon_shader.uniform_float(k, mat.float_dic[k])

                for k, v in mat.vector_dic.items():
                    toon_shader.uniform_float(k, v)

                bgl.glActiveTexture(bgl.GL_TEXTURE0)
                bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                    bgl.GL_CLAMP_TO_EDGE)  # TODO
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                    bgl.GL_CLAMP_TO_EDGE)
                toon_shader.uniform_int("depth_image", 0)

                for i, k in enumerate(mat.texture_dic.keys()):
                    bgl.glActiveTexture(bgl.GL_TEXTURE1 + i)
                    texture = mat.texture_dic[k]
                    bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture.bindcode)
                    bgl.glTexParameteri(bgl.GL_TEXTURE_2D,
                                        bgl.GL_TEXTURE_WRAP_S,
                                        bgl.GL_CLAMP_TO_EDGE)  # TODO
                    bgl.glTexParameteri(bgl.GL_TEXTURE_2D,
                                        bgl.GL_TEXTURE_WRAP_T,
                                        bgl.GL_CLAMP_TO_EDGE)
                    toon_shader.uniform_int(k, 1 + i)

                toon_bat.draw(toon_shader)
Esempio n. 30
0
    def make_humanoid(self, mesh):
        args = self.args
        self.bm = bmesh.new()
        head_size = self.head_size
        # region body

        # make neckneck
        neck_bone = self.get_humanoid_bone("neck")
        self.make_half_cube([head_size / 2, head_size / 2, neck_bone.length],
                            neck_bone.head_local)
        # make chest - upper and lower (肋骨の幅の最大値で分割)
        chest_bone = self.get_humanoid_bone("chest")
        shoulder_in = args.shoulder_in_width
        leftUpperArm_bone = self.get_humanoid_bone("leftUpperArm")
        # upper chest shell
        self.make_half_trapezoid(
            [head_size * 3 / 4, leftUpperArm_bone.head_local[0] * 2],
            [head_size * 3 / 4, shoulder_in],
            chest_bone.length,
            chest_bone.matrix_local,
        )
        # lower chest shell
        spine_bone = self.get_humanoid_bone("spine")
        self.make_half_trapezoid(
            [
                head_size * 3 / 4,
                (leftUpperArm_bone.head_local[0] - shoulder_in) * 2
            ],
            [head_size * 3 / 4, leftUpperArm_bone.head_local[0] * 2],
            spine_bone.length * 3 / 5,
            spine_bone.matrix_local @ Matrix.Translation(
                Vector([0, spine_bone.length * 2 / 5, 0])),
        )

        # make spine
        # make hips
        hips_bone = self.get_humanoid_bone("hips")
        hips_size = leftUpperArm_bone.head_local[0] * 2 * 1.2
        self.make_half_cube([hips_size, head_size * 3 / 4, hips_bone.length],
                            hips_bone.head_local)
        # endregion body

        # region arm
        left_arm_bones = [
            self.get_humanoid_bone(v)
            for v in HumanBones.left_arm_req + HumanBones.left_arm_def
            if v in args.armature_obj.data and args.armature_obj.data[v] != ""
            and args.armature_obj.data[v] in args.armature_obj.data.bones
        ]
        left_hand_bone = self.get_humanoid_bone("leftHand")
        for b in left_arm_bones:
            base_xz = [
                b.head_radius if b != left_hand_bone else args.hand_size / 2,
                b.head_radius,
            ]
            top_xz = [
                b.tail_radius if b != left_hand_bone else args.hand_size / 2,
                b.tail_radius,
            ]
            self.make_trapezoid(base_xz, top_xz, b.length, [0, 0, 0],
                                b.matrix_local)
        # TODO Thumb rotation
        # endregion arm

        # region leg
        # TODO
        left_leg_bones = [
            self.get_humanoid_bone(v)
            for v in HumanBones.left_leg_req + HumanBones.left_leg_def
            if v in args.armature_obj.data and args.armature_obj.data[v] != ""
            and args.armature_obj.data[v] in args.armature_obj.data.bones
        ]
        for b in left_leg_bones:
            bone_name = ""
            for k, v in self.args.armature_obj.data.items():
                if v == b.name:
                    bone_name = k
                    break
            if bone_name == "":
                head_x = b.head_radius
                head_z = b.head_radius
                tail_x = b.head_radius
                tail_z = b.head_radius
            elif "UpperLeg" in bone_name:
                head_x = hips_size / 2
                head_z = hips_size / 2
                tail_x = 0.71 * hips_size / 2
                tail_z = 0.71 * hips_size / 2
            elif "LowerLeg" in bone_name:
                head_x = 0.71 * hips_size / 2
                head_z = 0.71 * hips_size / 2
                tail_x = 0.54 * hips_size / 2
                tail_z = 0.6 * hips_size / 2
            elif "Foot" in bone_name:
                head_x = 0.54 * hips_size / 2
                head_z = 0.6 * hips_size / 2
                tail_x = 0.81 * hips_size / 2
                tail_z = 0.81 * hips_size / 2
            elif "Toes" in bone_name:
                head_x = 0.81 * hips_size / 2
                head_z = 0.81 * hips_size / 2
                tail_x = 0.81 * hips_size / 2
                tail_z = 0.81 * hips_size / 2
            self.make_trapezoid([head_x, head_z], [tail_x, tail_z], b.length,
                                [0, 0, 0], b.matrix_local)
        # endregion leg

        self.bm.to_mesh(mesh)
        self.bm.free()
        return