0 of 0

File information

Last updated

Original upload

Created by

KEI

Uploaded by

BWV997

Virus scan

Safe to use

Tags for this mod

22 comments

  1. ByronicAero
    ByronicAero
    • member
    • 11 kudos
    I am new 3D Animations and was wondering when you are done animating. Which "Outliner in Maya" do choose to export as fbx?
    I am using your "Skyrim_Animation_Rig_for_Maya" File
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      Hi there! Welcome to the world of 3D animations. I'm glad you're using this rig for your projects.
      When you're done animating and ready to export your work as an FBX file from Maya, you'll need to select a specific bone in the Outliner. For the Skyrim mod, the bone you should look for is named "NPC_s_Root_s__ob_Root_cb_". This is the top bone in the hierarchy for a human character in Skyrim.
      Here's a step-by-step guide to help you:

      1. Open the Outliner in Maya. You can usually find this in the Windows menu.
      2. In the Outliner, navigate through the list and find the bone named "NPC_s_Root_s__ob_Root_cb_".
      3. Select this bone. Make sure it's the only thing selected.
      4. Now, go to File > Export Selection. This opens the export window.
      5. In the export window, choose FBX as your file format.
      6.  Hit export, and you're done!

      If you have any more questions or need further assistance, feel free to ask. Happy animating!
    2. ByronicAero
      ByronicAero
      • member
      • 11 kudos
      Oh okay. Can I do this on any version of Maya? I am using 2024
    3. BWV997
      BWV997
      • premium
      • 148 kudos
      I have only tested and verified the process using Maya 2018.
      While the basic principles of exporting FBX files remain consistent across versions, I cannot guarantee that the process will be exactly the same.
      I mean, I guess maya2024 can do this too.

      It's now 2 AM here in Japan, so I'm going to call it a night. Feel free to reach out if you have more questions, and I'll get back to you as soon as I can. Goodnight!
    4. ByronicAero
      ByronicAero
      • member
      • 11 kudos
      Oh my apologies. I created a video on the issue I am having. You can check it out whenever you are available.
    5. BWV997
      BWV997
      • premium
      • 148 kudos
      hey Byronic.
      I've left a comment on your YouTube video. Please check it out when you can.
    6. ByronicAero
      ByronicAero
      • member
      • 11 kudos
      Hey BWV997! I saw the comment. I followed the new steps but still having some issues.

  2. MRN62
    MRN62
    • premium
    • 70 kudos
    Can i use this to make MCO animation
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      Modskyrim62

      That is what I'm curious about too. I've never tried MCO things, would you please test this rig out?? 
    2. TheShinyHaxorus
      TheShinyHaxorus
      • premium
      • 740 kudos
      You'd need a way to translate the root motion in the rig to the Anim Motion annotations that the AMR mod uses. There's a script from MikeNike (in Python) that would need to be edited for Maya as opposed to blender, but yeah.

      Spoiler:  
      Show
      import bpy
      import os
      import re
      from bpy_extras.io_utils import ExportHelper
      from bpy_extras.io_utils import ImportHelper
      from bpy.types import Operator
      from bpy.props import StringProperty
      from bpy.utils import register_class
      from math import log
      class hkanno_OT_output(Operator, ExportHelper): #----> invoke ExportHelper operator
          """for use with hkanno64, recommend you place your files inside working directory in your mod folder"""
          bl_idname = 'hkanno.txt_output' #-----------------> operator name
          bl_label = 'Export Annotations' #-----------------> button label for file browser
          bl_options = {'PRESET', 'UNDO'}
       
          filename_ext = '' #-------------------------------> filename extension (leave empty, I write the extensions after)
          
          filter_glob: StringProperty(
              default='*.txt', #----------------------------> filter files in browser to ONLY those with these extensions
              options={'HIDDEN'}
          )
       
          def execute(self, context):
              
              rig = 'control rig'
              referencetrack = 'root'
              skyrim_rig = 'skeleton.nif'
              scaleunits = 10
              hkannoversion = 'hkanno64.exe'
              framerate = bpy.context.scene.render.fps
              currentframe = bpy.context.scene.frame_current
              firstframe = bpy.context.scene.frame_start
              lastframe = bpy.context.scene.frame_end
              skeleton = bpy.data.armatures[skyrim_rig]
              export_root_motion = bpy.data.window_managers["WinMan"].export_root_motion
              export_root_rotation = bpy.data.window_managers["WinMan"].export_root_rotation
              
              bonecount = 1 #------------------------------> subtract bonecount by number of junk bones (bones in your skeleton that don't contribute to the hierarchy and are not meant to be processed in HCT) ex; NPC and skeleton.nif itself
              for bone in skeleton.bones:
                  bonecount += 1 #-------------------------> for each iteration, add 1 to the bonecount
              
              print('\n\n' + 'exported file:', self.filepath, '\n')
              count = 0
              
              for marker in bpy.context.scene.timeline_markers:
                  if (marker.frame >= firstframe) and (marker.frame <= lastframe): #--------> check if marker is within render timeline range
                      count = count + 1 #------------------> for each iteration, add 1 to count
              
              if export_root_motion == 1:
                  count = count + (lastframe - firstframe) # cheap way to add animmotion to NumAnnotations count without doing the loop we do later twice (since root motion is sampled every frame)
              else:
                  print('skipping root motion...')
                  
              if export_root_rotation == 1:
                  count = count + (lastframe - firstframe)
              else:
                  print('skipping root rotation... \n')
              duration = (round((lastframe - firstframe)/framerate, 2))
              
              f = open(self.filepath + '.txt', 'w') #------> open textfile at the chosen directory (self.filepath) and in write mode ('w')
              f.write('# numOriginalFrames:' + (str(lastframe - firstframe)) + '\n' +  # number of frames (found simply by subtracting the first frame from the last frame to find the difference)
                      '# duration:' + (str((lastframe - firstframe)/framerate)) + '\n' # duration of animation (found just by dividing the first formula by the scene framerate)
                      '# numAnnotationTracks: ' + (str(bonecount)) + '\n' # number of bones in skyrim skeleton
                      '# numAnnotations: '+ (str(count)) + '\n\n') #number of annotations
                      
              bpy.ops.screen.animation_cancel(restore_frame=False)# stop animation playback
              bpy.ops.screen.frame_jump() #----------------> Jump to first frame on render timeline
              startpos = bpy.data.objects[rig].pose.bones[referencetrack].location.copy()
              startposx = (round(startpos[0], 4))
              startposy = (round(startpos[1], 4))
              startposz = (round(startpos[2], 4))
              
              for currentframe in range(firstframe, lastframe): # Iterate over frames in render timeline
                  bpy.ops.screen.frame_offset(delta=+1) #--> For each iteration, jump one frame ahead
                  time = (round((currentframe - firstframe + 1) / framerate, 4)) # Calculate time value irrespective of render timeline offsets
                  
                  
                  # Here you can change the axis of orientation for the root motion calculation (In skyrim X is side to side, Y is forwards and backwards, Z is vertical)
                  locx = (round(bpy.data.objects[rig].pose.bones[referencetrack].location[0], 4))
                  locy = (round(bpy.data.objects[rig].pose.bones[referencetrack].location[1], 4))
                  locz = (round(bpy.data.objects[rig].pose.bones[referencetrack].location[2], 4))
                  normx = (locx-startposx)
                  normy = (locy-startposy)
                  normz = (locz-startposz)
                  
                  if export_root_motion == 1:
                      f.write((str(time)) + ' ' + 'animmotion' + ' ' + (str(normx*scaleunits)) + ' ' + (str(normy*scaleunits)) + ' ' + (str(normz*scaleunits)) + '\n')
                      print(time, 'animmotion', (normx*scaleunits), (normy*scaleunits), (normz*scaleunits))
              f.write('\n\n')
              
              bpy.ops.screen.animation_cancel(restore_frame=True)# stop animation playback
              bpy.ops.screen.frame_jump() #----------------> Jump to first frame on render timeline
              startrot = bpy.data.objects[rig].pose.bones[referencetrack].rotation_euler.copy()
              startrotz = (round(startrot[2], 4))
              
              for currentframe in range(firstframe, lastframe): # Iterate over frames in render timeline
                  bpy.ops.screen.frame_offset(delta=+1) #--> For each iteration, jump one frame ahead
                  time = (round((currentframe - firstframe + 1) / framerate, 4)) # Calculate time value irrespective of render timeline offsets
                  
                  rotz = (round(bpy.data.objects[rig].pose.bones[referencetrack].rotation_euler[2], 4))
                  normzr = (rotz-startrotz)
               
                  if export_root_rotation == 1:
                      f.write((str(time)) + ' ' + 'animrotation' + ' ' + (str(normzr*57.27)) + '\n')
                      print(time, 'animrotation', (normzr))
              f.write('\n\n')
              
              f1 = open(self.filepath + '.txt', 'a') #-----> append animevents to our text file (to keep things visually organized)
              for marker in bpy.context.scene.timeline_markers:
                  frame = marker.frame #-------------------> Basically the same as blah_blah.scene...timeline_markers.frame (gets the frame of a marker)
                  if (marker.frame >= firstframe) and (marker.frame <= lastframe): # check if marker is within render timeline range
                      anno = (str(marker)).split('"')[1]
                      f.write((str((frame - firstframe)/framerate)) + ' ' + (str(anno)) + '\n')
                      print(((frame - firstframe)/ framerate), anno)
              f.close()
              f1.close()
              
              f2 = open(self.filepath + '.bat', 'w')
              f2.write(hkannoversion + ' ' + 'update' + ' ' + '-i' + ' ' + '"' + (os.path.basename(self.filepath)) + '.txt' + '"'  + ' ' + '"%~1"' + ' ' + '"' + (os.path.basename(self.filepath)) + '.hkx' + '"')
              f2.close()
              print('bones in rig: ', bonecount)
              print('frames: ', (str(lastframe - firstframe)))
              print('duration: ', (str((lastframe - firstframe)/framerate)))
              print('framerate: ', framerate)
              
              return {'FINISHED'}
          
          
      class hkanno_OT_input(Operator, ImportHelper): #-----> invoke ExportHelper operator
          """import markers from text file"""
          bl_idname = 'hkanno.txt_input' #-----------------> operator name
          bl_label = 'Import Annotations' #----------------> button label for file browser
          bl_options = {'PRESET', 'UNDO'}
       
          filename_ext = '' #------------------------------> filename extension (leave empty, I write the extensions after)
          
          filter_glob: StringProperty(
              default='*.txt', #---------------------------> filter files in browser to ONLY those with these extensions
              options={'HIDDEN'}
          )
          
          def execute(self, context):
              
              bpy.context.scene.timeline_markers.clear()
              
              firstframe = bpy.context.scene.frame_start
              framerate = bpy.context.scene.render.fps
              
              print('file chosen: ' + (self.filepath))
              f = open(self.filepath, 'r')
              
              textfile = f.readlines()
              for line in textfile:
                  if 'animmotion' in line:
                      line = line.replace('.' , '')
                  elif 'numAnnotationTracks' in line:
                      line = line.replace('.', '')
                  elif 'numAnnotations' in line:
                      line = line.replace('.', '')
                  elif 'duration' in line:
                      line = line.replace('.', '')
                  elif 'numOriginalFrames' in line:
                      line = line.replace('.', '')
                  else:
                      marker = line.split(' ', 1)
                      markername = (marker[-1])
                      markername2 = markername.replace('\n', '')
                      time = re.findall('\d.\d+', line)
                      floatconversion = [float(F) for F in time]
                      for i in floatconversion:
                          Frame = (int((i*framerate)+firstframe))
                          bpy.context.scene.timeline_markers.new((str(markername2)), frame = Frame)
                      print(markername)
                  
                  
              return {'FINISHED'}
          
          
      class hkanno_OT_clear(bpy.types.Operator):
          """Clear markers from scene"""
          bl_idname = 'hkanno.markers_clear'
          bl_label = 'Clear Markers'
          
          
          def execute(Self, Context):
              bpy.context.scene.timeline_markers.clear()
              
              return {'FINISHED'}
       
       
      def register():
          bpy.utils.register_class(hkanno_OT_output)
          bpy.utils.register_class(hkanno_OT_input)
          bpy.utils.register_class(hkanno_OT_clear)
          
      def unregister():
          bpy.utils.unregister_class(hkanno_OT_output)
          bpy.utils.unregister_class(hkanno_OT_input)
          bpy.utils.unregister_class(hkanno_OT_clear)
          
      if __name__ == '__main__':
          register()
       
      #bpy.ops.hkanno.txt_output('INVOKE_DEFAULT')
    3. BWV997
      BWV997
      • premium
      • 148 kudos
      hmmm, Thanks for info Haxorus.
  3. RhanTegoth654
    RhanTegoth654
    • member
    • 30 kudos
    Hello there !

    I'm so GLAD to see a rig in Maya haha ! Thank you so much for this !

    May I ask if it's possible to export paired rigs, for killmoves ? Or could it work for sexlab also ?
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      RhanTegoth654

      This rig would works for SL animations because they are not made from paired rig, they are just a 2 single animations as I mentioned in the description page. 

      It’s difficult to export paired rig from Skyrim. because there is no paired skeleton in the game data(archive). 
      I want you to read a article below especially “The Theory Behind All of This” section. You may understand why I can’t export it.https://www.nexusmods.com/skyrim/mods/49311/

      Does my answer make sense?? 
    2. RhanTegoth654
      RhanTegoth654
      • member
      • 30 kudos
      Hi, thank you a lot !

      Yes, totally, i understand, thanks. I just have a question : If i want to replace, for exemple a SL anim, do I have to touch the behaviors file or not ?

      I made anims for FO4, just start with skyrim and in Fallout, there are a not the behaviors things.
    3. BWV997
      BWV997
      • premium
      • 148 kudos
      No, you don't have to touch behavior files only if you just wanna replace SL anims.
    4. RhanTegoth654
      RhanTegoth654
      • member
      • 30 kudos
      Thank you for the informations ! :) Keep up the excellent job ! you're a life saver :D
  4. Violet2023
    Violet2023
    • member
    • 0 kudos
    Happy New Year.

    Apologies if I missed something as I am pretty new to Maya animation. However,  I got a couple of errors.

    1. Does this require ngSkinTools or a similar plugin? I got the following in the Script Editor when I opened the file - "Unrecognized node type 'ngst2SkinLayerData'; preserving node information during this session."

    2.  The Control Picker File seems to reference some images such as: "image.path": "D:/warehouse/refs/refs/Window27.png". However, these don't seem to have been included?

    Thanks,
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      Hi violet2023 

      1. Yes I used ngskintools, Please ignore that error since I tweaked body mesh's weight (which was not necessary at all) then forgot to delete that. 
      2. That’s my mistakes too. I re-uploaded them as Miscellaneous files. please check it out. 

      Thank you for telling me.
      Happy new year.
  5. Sigerious
    Sigerious
    • premium
    • 471 kudos
    Only 3rd person?
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      Yes only 3rd person. Actually I have tried convert 1st person mesh and skeleton but failed. Thanks for asking.
  6. DDCrusader
    DDCrusader
    • premium
    • 32 kudos
    Oh, this looks promising. Might as well try it :-)

    Thanks and Happy New Year!
    1. BWV997
      BWV997
      • premium
      • 148 kudos
      Happy new year pal!