Jump to content

Recommended Posts

In addition to issue with flickering.

Some thoughts and calculations ;)

Skyrim uses ZYX-Euler (i don't remember correct left or right) system. All transforms to Blender's system while import and back while export sometimes makes me crazy.
Why flickering happens with Thigh bones more frequently. Maybe because they default data in skeleton. For example, LThig has X: 177.877319; Y: -5.655318; Z: 177.616911 in Euler rotation.
With transforming it to axis-angle system we got x: -0.01985; y: 0.99965; z: -0.01747, but angle IS: 185.70, and exceeds 180 degrees. In 'common' cases this is not 'normal', like counting angles over 360 degrees, but accepted. For example while animating some mesh in blender with using 3600 in Eulers data for some of the axis will cause this mesh to rotate exactly 10 times.
Quaternion can be created from this rough data with two ways:
quat1 = Quaternion(-0.049721, -0.01985, 0.99965, -0.01747))
i.e. via direct using w-x-y-z from Nifscope, OR
quat2 = Quaternion((-0.01985, 0.99965, -0.01747), radians(185.7))
i.e. via axis-angle data.

They ARE EQUAL, but NEGATIVE to each-other.

 

Link to comment

To Vpoteryaev :

 

Sorry for the misunderstanding about flickering.

I am afraid I cannot be of much help.

 

I have attempted to use your tool to make a paired animation.

 

Basically, here is the attempt to make a paired animation rig in blender (base on the information by kentington)

 

 

The first step involves importing two sets of skeletons - either two humans or a human and a creature, depending on your intended animation - into Max. You'll need to link both skeletons beneath a bone named PairedRoot, then apply the prefix "2_" to the second skeleton's bones, as shown below:

[PairedRoot]
->[NPC]
->->[NPC Root]
->[2_]
->->[2_NPC Root]

Since the NifTools importer will overwrite any bone with a duplicate name, your best bet is to import the second skeleton first and apply the prefix (highlight all bones, click Tools->Rename Objects, check Prefix and enter "2_" into the box). Make sure to change "2_NPC" to "2_" if it exists, or create it if it does not. Move the second skeleton to its desired starting position and orientation, import meshes if desired, and animate the two actors as you normally would.

 

Thus :

 

1 - import a nif skeleton in blender using Skyrim nif-data utils

2 - select the skeleton, move it and rotate 180° (so that the two imported skeletons won't be at the same place)

 

3 - rename 'NPC' bone as '2_' and prefix other bones name's with '2_'
This can be achieved running the following script :

import bpy

# Active object
ob = bpy.context.object

if ob.type == 'ARMATURE':
    armature = ob.data

    for bone in armature.bones:
        print(bone.name)
        temp=bone.name
        if temp='NPC'
            bone.name='2_'
        else
            bone.name='2_'+temp
        print(bone.name)

4- import a second nif skeleton in blender using Skyrim nif-data utils

5 - add a new bone, name it [PairedRoot]

 

6 - Make bone [2_] and bone [NPC] children of bone [PairedRoot]

 

7- Export the skeleton as a nif file using Skyrim nif-data utils

 

8 - Create a basic animation (frame by frame) on each of the imported skeleton.

 

9 - Export the animation as a kf file using Skyrim nif-data utils.

 

 

 

For now, I have only tested the result in NIFSKOPE (SKYRIM not yet reinstalled).

 

The paired skeleton seem to open alright in NIFSKOPE.

The animation on the skeleton without prefix imports in NIFSKOPE

The other animation does not show.

 

I have to think it over a bit.

 

Best regards

 

PS : I don't intend to hijack the thread. If you feel this should be continued elsewhere, I'll move it.

Your wonderful tool just re-opened this perspective of paired animation.

 

 

 

 

Link to comment

To Vpoteryaev :

 

It seems to me these information may be appropriate for "baking" animation from IK constraints :

http://blender.stackexchange.com/questions/40711/how-to-convert-quaternions-keyframes-to-euler-ones-in-several-actions

 

The script referenced below is more or less equivalent to :

OBJECT MODE : menu object -> animation -> bake action

POSE MODE : menu pose -> animation -> bake action

automate baking of armature actions in python

Better to work on the copy of an action as all constraints are deleted in the process....

 

Best regards

Link to comment

To Vpoteryaev :

 

Sorry for the misunderstanding about flickering.

I am afraid I cannot be of much help.

 

I have attempted to use your tool to make a paired animation.

 

 

Basically, here is the attempt to make a paired animation rig in blender (base on the information by kentington)

 

 

The first step involves importing two sets of skeletons - either two humans or a human and a creature, depending on your intended animation - into Max. You'll need to link both skeletons beneath a bone named PairedRoot, then apply the prefix "2_" to the second skeleton's bones, as shown below:

 

[PairedRoot]

->[NPC]

->->[NPC Root]

->[2_]

->->[2_NPC Root]

 

Since the NifTools importer will overwrite any bone with a duplicate name, your best bet is to import the second skeleton first and apply the prefix (highlight all bones, click Tools->Rename Objects, check Prefix and enter "2_" into the box). Make sure to change "2_NPC" to "2_" if it exists, or create it if it does not. Move the second skeleton to its desired starting position and orientation, import meshes if desired, and animate the two actors as you normally would.

 

Thus :

 

1 - import a nif skeleton in blender using Skyrim nif-data utils

2 - select the skeleton, move it and rotate 180° (so that the two imported skeletons won't be at the same place)

 

3 - rename 'NPC' bone as '2_' and prefix other bones name's with '2_'

This can be achieved running the following script :

 

import bpy

 

# Active object

ob = bpy.context.object

 

if ob.type == 'ARMATURE':

    armature = ob.data

 

    for bone in armature.bones:

        print(bone.name)

        temp=bone.name

        if temp='NPC'

            bone.name='2_'

        else

            bone.name='2_'+temp

        print(bone.name)

 

4- import a second nif skeleton in blender using Skyrim nif-data utils

5 - add a new bone, name it [PairedRoot]

 

6 - Make bone [2_] and bone [NPC] children of bone [PairedRoot]

 

7- Export the skeleton as a nif file using Skyrim nif-data utils

 

8 - Create a basic animation (frame by frame) on each of the imported skeleton.

 

9 - Export the animation as a kf file using Skyrim nif-data utils.

 

For now, I have only tested the result in NIFSKOPE (SKYRIM not yet reinstalled).

 

The paired skeleton seem to open alright in NIFSKOPE.

The animation on the skeleton without prefix imports in NIFSKOPE

The other animation does not show.

 

I have to think it over a bit.

 

Best regards

 

 

PS : I don't intend to hijack the thread. If you feel this should be continued elsewhere, I'll move it.

Your wonderful tool just re-opened this perspective of paired animation.

I'm very glad that you give me ideas. Please, don't hesistate to post new ones.

Even they a bit forwarding current stages of my work, but this thread will not disappears at moment. At any time I can reread that have been posted by you or someone else.

 

My first animation is out - so tested last fix with 'flickering', seems work.

Next step - import bodies. And of course, catching BUGs. ;)

 

Kind Regards.

Link to comment

To Vpoteryaev :

 

 

Well, you are right. The IK bones will probably have no effect on the displayed animation in game as the mesh is only weight painted against the deform bones of the skeleton.

As I understand it, the 'blender nif plugin' is said to be able to import mesh and skeleton and export mesh and skeleton.

I refer to this one : blender_nif_plugin-2.6.0a0.dev4-20-jun-16

The 'skyrim nif-data utils' allows to import skeleton and export skeleton and animation.

Thus, with these two tools installed, I should be able to import a model from skyrim with its skeleton, make an animation and export it as a kf file without ever using blender 2.49.

Then, use khxcmd on the kf animation file and the nif skeleton file to produce the hkx animation file that can be used in SKYRIM.

 

I am interested in making wrestling animation.

I've read about a trick to make paired animation : zaz paired animation rig and paired animation export tutorial by kentington

It is roughly based on creating a paired root then importing a first skeleton prefixing its bone by 2_and then importing a second skeleton.

I have unfortunately not found any rig demonstrating this in blender.

Have you ?

Do you think this approach is compatible with your tool (I am thinking of the xpmse limitation you wrote about) ?

 

For further export of the paired animation, I have read the limitation of hkxcmd can be overriden by an appropriate "switch" -s.

The method is described further in the tutorial : animating in skyrim with custom bones (blender/hkxcmd)

 

Normally, green light : all the tools are available an newest blender.

 

Time for testing...

 

Best regards

 

 

After a short rest i did quick test

Even at current stage you can create PAIRED animations.

How I did test.blend with canine and human.

1. Import human skeleton, attach to it body

2. IN ANOTHER Blender instance import wolf's skeleton, in 'object mode' copy it to buffer

3. Switch to first window, paste wolf's skeleton, attach to it wolf's body-parts

As nif-data utils CAN IMPORT ANY skeleton this can be made with any creature (even for creature-creature animations)

I see no limit to create tripple-foursome, up to 5 actors that SL supports (if you plan to create SL-animations)

4. Create animation

For quick test I have to used SexLab functionality.

5. With wolf's skeleton selected export animation as 'paired_test_canine.kf'

6. select humans skeleton, export as 'paired_test_human.kf'

7. convert them to .hkx with named accordingly: 'paired_test_canine_A2_S1.hkx' and 'paired_test_human_A1_S1.hkx'

The way to integrate them into SL - your troubles.

I see no reason to reastrain from usage of my 'AnimTester' that i created somehow for llabsky and simple attached test animations to it.

All FNIS praparations (i.e. behavior files created.....)

After installation just re-run 'FNIS for Users'.

Go to 'AnimTester' MCM and ensure that '(AT) paired_test nif-data (wolf)' and '(AT) paired_test nif-data (dog)' are selected.

Re-register SexLab animations.

For testing in-game look for, or summon, or PlaceAtMe any dog or wolf (even DeathHound)

Select it with 'N' key for SexLab selection

Goto SexLab's 'Animation Editor' tab, select in animation '(AT) paired_test nif-data (dog)' or '(AT) paired_test nif-data (wolf)' and play.

Everything works.

 

NOTE: I see no restrictions with copy-paste buffer to move already fully created rigs between .blend files

 

Kind Regards.

blend and kfs.7z

AnimTester.7z

Link to comment

To Vpoteryaev :

Thank you for the information. I have to try this.

 

I am presently trying to build a rig (FK/IK) to prepare for animation.

 

Looking at the imported rig, I realized some of the bones had weird angles.

 

 

At the moment, I have spotted :

- NPC R PreBreast or NPC L preBreast (asymetry)

- Belly

- NPC L PreButt or NPC R Prebutt (asymetry)

- NPC R ForearmTwist1, NPC R ForearmTwist2

- NPC R Hand

- NPC L ForearmTwist1, NPC L ForearmTwist2

- NPC L Hand

- NPC Spine

 

I won't be using wings bones, skirtbones and special bones.

So, my check is not thorough and there might be more bones to consider.

An advanced rigger expertise would be needed to spot all of them.

 

The forearm twist bones should be aligned with Forearm bone, just like the upperarm twist bones are aligned with upperarm bone.

The hand bones should be aligned with the hand.

The spine bone should be more vertical.

The prebutt and prebreast bone should be symetrical L & R.

belly should be pointing towards front.

 

 

 

I have not experimented enough to  find a work around.

Need to experiment with the rig further.

 

Best regards.

 

 

Link to comment

To Vpoteryaev :

Thank you for the information. I have to try this.

 

I am presently trying to build a rig (FK/IK) to prepare for animation.

 

Looking at the imported rig, I realized some of the bones had weird angles.

 

 

At the moment, I have spotted :

- NPC R PreBreast or NPC L preBreast (asymetry)

- Belly

- NPC L PreButt or NPC R Prebutt (asymetry)

- NPC R ForearmTwist1, NPC R ForearmTwist2

- NPC R Hand

- NPC L ForearmTwist1, NPC L ForearmTwist2

- NPC L Hand

- NPC Spine

 

I won't be using wings bones, skirtbones and special bones.

So, my check is not thorough and there might be more bones to consider.

An advanced rigger expertise would be needed to spot all of them.

 

The forearm twist bones should be aligned with Forearm bone, just like the upperarm twist bones are aligned with upperarm bone.

The hand bones should be aligned with the hand.

The spine bone should be more vertical.

The prebutt and prebreast bone should be symetrical L & R.

belly should be pointing towards front.

 

I have not experimented enough to  find a work around.

Need to experiment with the rig further.

 

Best regards.

 

 

In Blender it mostly has no matter how bones are aligned.

In current NifTools builds (I tried them) bones alignment in Blender works only one way, regardless settings due logical errors in scripts. But in Blender 2.49 NifTools you can choose "Tail" or "Tail+Roll". This choice works in my scripts too. Even in my .blend 'example' files is used "Tail", for myself i prefer "Tail+Roll".

It's done for 'visual' kindness. Also, how else 'zero'-length bone can be displayed in Blender?

While exporting a reverce convertation to 'original' skeleton data is performed.

Anyway, mostly for animations exact 'default' bone's position has no matter (sometimes for me is too hard to explain smth. with English), because relative rotations/offsets from 'default' position are taken into account.

 

Kind Regards.

Link to comment

To Vpoteryaev :

I found it is possible to call other programs within blender.

With this script, I managed to run hkxcmd for blender, provided all the necessary files are in the same root as the blend file.

 

 

import bpy
import os
import sys

import subprocess


FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')

FileName_skeletonhkx=os.path.join(os.path.dirname(bpy.data.filepath), 'skeleton.hkx')
FileName_empty_newkf=os.path.join(os.path.dirname(bpy.data.filepath), 'empty_new.kf')
FileName_empty_newhkx=os.path.join(os.path.dirname(bpy.data.filepath), 'empty_new.hkx')

subprocess.call([FileName_hkxcmd,'convertkf',FileName_skeletonhkx,FileName_empty_newkf,FileName_empty_newhkx])

 

 

It is still not very convenient. I have tried to use blender GUI to allow the use of file browser (hkxcmd.exe is supposed to be in the same directory as blend file).

Hereafter is my attempt.

 

 

import bpy
from bpy.props import (StringProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )
                       
import os
import sys

import subprocess

# ------------------------------------------------------------------------
#    ui
# ------------------------------------------------------------------------

class Path_shkx(PropertyGroup):

    path_shkx = StringProperty(
        name="truc",
        description="Path to hkx skeleton file",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')

        
class Path_akf(PropertyGroup):
          
    path_akf = StringProperty(
        name="",
        description="Path to kf animaton file",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')

class Path_ahkx(PropertyGroup):
        
     path_ahkx= StringProperty(
        name="",
        description="Path to hkx animaton file",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')
        

class OBJECT_PT_my_panel(Panel):
    bl_idname = "OBJECT_PT_my_panel"
    bl_label = "hkxcmd convert kf file to hkx file"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        scn = context.scene
        
        col = layout.column(align=True)
        col.prop(scn.shkx, "path_shkx", text="Skeleton hkx file")
        
        col = layout.column(align=True)
        col.prop(scn.akf, "path_akf", text="Animation kf file")
        
        col = layout.column(align=True)
        col.prop(scn.ahkx, "path_ahkx", text="Animation hkx file")
        
        col = layout.column(align=True)
        col.operator("convert2.hkx")
        
#
#   The OK button in the error dialog
#
class OkOperator(bpy.types.Operator):
    bl_idname = "convert2.hkx"
    bl_label = "OK"
    def execute(self, context):
        # print the path to the console
        scn = context.scene
        
        FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')
        
        FileName_skeletonhkx = bpy.path.abspath(scn.shkx.path_shkx)
        FileName_animationkf = bpy.path.abspath(scn.akf.path_akf)
        FileName_animationhkx = bpy.path.abspath(scn.ahkx.path_ahkx)

        subprocess.call([FileName_hkxcmd,'convertkf',
        FileName_skeletonhkx,FileName_animationkf,FileName_animationhkx])
        
        print('passed')
        
        return {'FINISHED'}
        

# ------------------------------------------------------------------------
#    register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.shkx = PointerProperty(type=Path_shkx)
    bpy.types.Scene.akf = PointerProperty(type=Path_akf)
    bpy.types.Scene.ahkx = PointerProperty(type=Path_ahkx)


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.shkx
    del bpy.types.Scene.ahkx
    del bpy.types.Scene.akf

    
    

if __name__ == "__main__":
    register()

 


I suspect the file browser gives a relative path whereas hkxcmd expects an absolute path.

 

Do you have any clue about solving the problem ?

 

Edit : I feel I have solved the problem....

My bad knowledgde of blender python

 

Best regards

 

 

Link to comment

To Vpoteryaev :

 

I thank you for your useful advice  and explanations.

I think I can find a way to create rig bones on top of the skeleton to simplfy the animation job.

 

Best regards

 

Edit : I found the kind of rig I intended to work on already exists for blender.

 

This custom rig is provided with a script that allows to get a hkx animation file directly.

In fact, some steps with KFmaker.exe and hkxcmd.exe are scripted.

 

I wish I had screened the script earlier. I would have acquired some knowledge about filepath handling in blender.

Still need to translate the web pages and understand the rig functionality.

 

I seems to me this rig is not based on XPMSE.

 

 

 

 

 

Link to comment

To vpoteryaev :

 

Your work on the nif data utils is very inspiring.

Your breaktrough gave me the energy to make this little script tu use hkcmd from blender.

- ahkx -> kf

- ahkx -> akhx xml

- ahkx xml -> ahkx

- ahkx + shkx -> kf


 

 

import bpy
from bpy.props import (StringProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )
                       
import os
import sys

import subprocess

# ------------------------------------------------------------------------
#    ui
# ------------------------------------------------------------------------

class Path_shkx(PropertyGroup):

    path_shkx = StringProperty(
        name="",
        description="Path to hkx skeleton file",
        default="",
        maxlen=1024,
        subtype='FILE_PATH')

        
class Path_akf(PropertyGroup):
          
    path_akf = StringProperty(
        name="",
        description="Path to kf animaton file",
        default="*.kf",
        options={'HIDDEN'},
        maxlen=1024,
        subtype='FILE_PATH')

class Path_ahkx(PropertyGroup):
        
     path_ahkx= StringProperty(
        name="",
        description="Path to hkx animaton file",
        default="*.hkx",
        maxlen=1024,
        subtype='FILE_PATH')
        
class OBJECT_PT_Converthkx2kf_panel(Panel):
    bl_idname = "OBJECT_PT_Converthkx2kf_panel"
    bl_label = "hkxcmd convert hkx file to kf file"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "HKXCMD"
    bl_context = "objectmode"
    
    def draw(self, context):
        layout = self.layout
        scn = context.scene
        
        col = layout.column(align=True)
        col.prop(scn.ahkx, "path_ahkx", text="Animation hkx file")
        
        col = layout.column(align=True)
        col.operator("convert2.kf")
        
#
#   The <Convert to kf> button in the error dialog
#
class RunConvertkf(bpy.types.Operator):
    bl_idname = "convert2.kf"
    bl_label = "Convert to kf"
    def execute(self, context):
        # print the path to the console
        scn = context.scene
        print(scn.ahkx.path_ahkx)
        
        FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')
        FileName_animationhkx = bpy.path.abspath(scn.ahkx.path_ahkx)
        print(FileName_animationhkx)
        
        FileName_skeletonhkx=os.path.join(os.path.dirname(bpy.data.filepath), 'skeleton.hkx')
        
        # convert hkx files to kf files
        subprocess.call([FileName_hkxcmd,'exportkf',FileName_animationhkx])
        
        print('passed')
        
        return {'FINISHED'}         
        


class OBJECT_PT_Convert2hkx_panel(Panel):
    bl_idname = "OBJECT_PT_Convert2hkx_panel"
    bl_label = "hkxcmd convert kf file to hkx file"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "HKXCMD"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        scn = context.scene
        
        col = layout.column(align=True)
        col.prop(scn.shkx, "path_shkx", text="Skeleton hkx file")
        
        col = layout.column(align=True)
        col.prop(scn.akf, "path_akf", text="Animation kf file")
        
        col = layout.column(align=True)
        col.prop(scn.ahkx, "path_ahkx", text="Animation hkx file")
        
        col = layout.column(align=True)
        col.operator("convertkf2.hkx")
        
#
#   The <Convert to hkx> button in the error dialog
#
class RunConvert2hkx(bpy.types.Operator):
    bl_idname = "convertkf2.hkx"
    bl_label = "Convert to hkx"
    def execute(self, context):
        # print the path to the console
        scn = context.scene
        print(scn.shkx.path_shkx)
        
        FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')
        
        FileName_skeletonhkx = bpy.path.abspath(scn.shkx.path_shkx)
        # FileName_skeletonhkx = os.path.abspath(scn.shkx.path_shkx)
        FileName_animationkf = bpy.path.abspath(scn.akf.path_akf)
        FileName_animationhkx = bpy.path.abspath(scn.ahkx.path_ahkx)
        print(FileName_skeletonhkx)
        print(FileName_animationkf)
        print(FileName_animationhkx)

        subprocess.call([FileName_hkxcmd,'convertkf',FileName_skeletonhkx,FileName_animationkf,FileName_animationhkx])
        
        print('passed')
        
        return {'FINISHED'}
        
class OBJECT_PT_Converthkx2xml_panel(Panel):
    bl_idname = "OBJECT_PT_Converthkx2xml_panel"
    bl_label = "hkxcmd convert hkx file to xml file"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "HKXCMD"
    bl_context = "objectmode"
    
    def draw(self, context):
        layout = self.layout
        scn = context.scene
        
        col = layout.column(align=True)
        col.prop(scn.ahkx, "path_ahkx", text="hkx file")
        
        col = layout.column(align=True)
        col.operator("convert2.xml")
        
#
#   The <Convert to xml> button in the error dialog
#
class RunConvertxml(bpy.types.Operator):
    bl_idname = "convert2.xml"
    bl_label = "Convert to xml"
    def execute(self, context):
        # print the path to the console
        scn = context.scene
        print(scn.ahkx.path_ahkx)
        
        FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')
        FileName_animationhkx = bpy.path.abspath(scn.ahkx.path_ahkx)
        print(FileName_animationhkx)
        
        FileName_skeletonhkx=os.path.join(os.path.dirname(bpy.data.filepath), 'skeleton.hkx')
        
        # convert hkx files to xml hkx files
        subprocess.call([FileName_hkxcmd,'convert',FileName_animationhkx])
        
        print('passed')
        
        return {'FINISHED'}        


        

class OBJECT_PT_Convertxml2hkx_panel(Panel):
    bl_idname = "OBJECT_PT_Convertxml2hkx_panel"
    bl_label = "hkxcmd convert xml file to hkx file"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "HKXCMD"
    bl_context = "objectmode"
    
    def draw(self, context):
        layout = self.layout
        scn = context.scene
        
        col = layout.column(align=True)
        col.prop(scn.ahkx, "path_ahkx", text="Animation hkx file") # placeholder : modify this
        
        col = layout.column(align=True)
        col.operator("convertxml2.hkx")
        
#
#   The <Convert to xml> button in the error dialog
#
class RunConvertxml(bpy.types.Operator):
    bl_idname = "convertxml2.hkx"
    bl_label = "Convert to hkx"
    def execute(self, context):
        # print the path to the console
        scn = context.scene
        print(scn.ahkx.path_ahkx)
        
        FileName_hkxcmd = os.path.join(os.path.dirname(bpy.data.filepath), 'hkxcmd.exe')
        FileName_animationhkx = bpy.path.abspath(scn.ahkx.path_ahkx)
        print(FileName_animationhkx)
        
        FileName_skeletonhkx=os.path.join(os.path.dirname(bpy.data.filepath), 'skeleton.hkx')
        
        # convert hkx files to xml hkx files
        subprocess.call([FileName_hkxcmd,'convert -v: win32',FileName_animationhkx])
        
        print('passed')
        
        return {'FINISHED'}           


# ------------------------------------------------------------------------
#    register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.shkx = PointerProperty(type=Path_shkx)
    bpy.types.Scene.akf = PointerProperty(type=Path_akf)
    bpy.types.Scene.ahkx = PointerProperty(type=Path_ahkx)


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.shkx
    del bpy.types.Scene.ahkx
    del bpy.types.Scene.akf

    
    

if __name__ == "__main__":
    register()

 

 

 

Still needs testing, polishing and advices.

 

edit : I forgot about the handbook,

this is a blender script,

copy the script,

paste it in a text window in blender

run the script,

you get a new panel.

This panel allows to browse for the files and run hkxcmd from blender.

It allows to perform the following conversion :

- hkx animation file -> kf animation file,

- hkx animation file -> hkx xml animation file

- hkx xml animation file -> hkx animation file

- kf animation file + skeleton animation file -> hkx animation file

 

About this one, does the '-s' switch really allows to export all bones ?

See this post

 

Best regards

Link to comment

To vpoteryaev :

 

Thank you for the tip of copying/pasting skeleton from one instanciation of blender to another.

I am gathering the required elements to start animation.

I think I'll try to animate basic moves of the viking wrestling GLIMA.

 

My work flow should be :

- open animation N3 custom rig (see upwards) in blender,

- animate with it,

- open an other instanciation of blender,

- import XPMSE skeleton in this instanciation  with your tool,

- copy/paste XPMSE skeleton

- copy bone position from the animate rig to XPMSE rig (probably script),

- export animation with your tool as a kf file,

- ...

 

Best regards

 

 

Link to comment

To vpoteryaev :

 

I found some interesting stuff about hkx animation format :

havok binary files

some example code from havok

a good explanation of spline compressed animation

an other  interesting explanation (less illustrated)

 

from first article and other readings, I understand skyrim uses spline compression to store skeletal animation.

It means  there is no simple correspondance between hkx compressed format and input animation.

One has to use the compression/decompression algorithms.

The two last links describe the type of algorithm that cab be used for spline compression and data storage.

From second link, a demo of spline compression in havok, I guess the spline compression may use 40-48 bits to store rotation as quaternions.

 

In the thread "havok binary file", the fifth page reports a C# code that allows to convert hkx skeleton to smd format

hkx2smd

edit : volfin quotation : "This is a project I started last year for Alien:Isolation, it's a HKX converter that outputs SMD skeleton. It works with 2012.2.0 and 2010.2.0, I had intended to take it all the way with support for many versions, and animation output, but I simply moved on to other projects. It's written in C#, a lot of the file structure is defined at the top of Program.cs, and maybe will help people, so I'm making the code public."

 

edit edit : I forgot to add the smd file can be imported in blender using blender source tool from steamreview.org

It is still a two step partial import (skeleton only). Like many others I would prefer to select my files, press a button and get the result.

 

Unfortunalety, this program hkx2smd is beyond my present understanding of coding : generic class, MarshalAs,...

I probably won't be able to make use of these pieces of information to build a code within blender in a reasonable time.

But making it available here, I hope one of the talented people  here will be able to use it somehow.

 

Best regards

 

Link to comment

Would someone be kind enough to explain to me (ELI5) how to install the prerequisites for this?

The link to github for Pyffi 2.2.3 and nifxml-0.7.1.0 seems to be for source code.  I have no idea how to build a Python Module or what is to be done with the nifxml.  I have Pyffi 2.2.2 installed and I have the nifxml that is bundled with Nif Tools; but I presume that that isn't enough, since Blender will not install the plugin.

 

I'm an artist, not a programmer, dammit........LOL.  ;)

 

Any assistance will be greatly appreciated. 

 

NM... I got it installed.  :angel:

 

Aaaaaaaaand....... I get this error, so I don't have it installed correctly.... <sigh>

 

 

Traceback (most recent call last):
File "C:\Blender Foundation 276\2.78\scripts\modules\addon_utils.py", line 330, in enable
mod = __import__(module_name)
File "C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender\2.78\scripts\addons\io_nifdata\__init__.py", line 47, in
from . import import_nifdata
File "C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender\2.78\scripts\addons\io_nifdata\import_nifdata.py", line 43, in
import pyffi.spells.nif
ImportError: No module named 'pyffi'

 

Edited by Tweens
Link to comment

Would someone be kind enough to explain to me (ELI5) how to install the prerequisites for this?

The link to github for Pyffi 2.2.3 and nifxml-0.7.1.0 seems to be for source code.  I have no idea how to build a Python Module or what is to be done with the nifxml.  I have Pyffi 2.2.2 installed and I have the nifxml that is bundled with Nif Tools; but I presume that that isn't enough, since Blender will not install the plugin.

 

I'm an artist, not a programmer, dammit........LOL.  ;)

 

Any assistance will be greatly appreciated. 

 

NM... I got it installed.  :angel:

 

Aaaaaaaaand....... I get this error, so I don't have it installed correctly.... <sigh>

 

 

Traceback (most recent call last):

File "C:\Blender Foundation 276\2.78\scripts\modules\addon_utils.py", line 330, in enable

mod = __import__(module_name)

File "C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender\2.78\scripts\addons\io_nifdata\__init__.py", line 47, in

from . import import_nifdata

File "C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender\2.78\scripts\addons\io_nifdata\import_nifdata.py", line 43, in

import pyffi.spells.nif

ImportError: No module named 'pyffi'

 

Unpack downloaded 'pyffi-pyffi-2.2.3.zip', inside unpacked data run 'pyffi-pyffi-2.2.3\install.bat'. To check that all installed, goto '[blender_folder]\2.78\python\lib\site-packages\' and check 'pyffi' folder exists.

To continue you have to go to path '[blender_folder]\2.78\python\lib\site-packages\pyffi\formats\nif\nifxml\' and place into 'nif.xml' from 'nifxml-0.7.1.0.zip'

In your case [blender_folder] is 'C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender'

 

Kind Regards.

Link to comment

 

Unpack downloaded 'pyffi-pyffi-2.2.3.zip', inside unpacked data run 'pyffi-pyffi-2.2.3\install.bat'. To check that all installed, goto '[blender_folder]\2.78\python\lib\site-packages\' and check 'pyffi' folder exists.

To continue you have to go to path '[blender_folder]\2.78\python\lib\site-packages\pyffi\formats\nif\nifxml\' and place into 'nif.xml' from 'nifxml-0.7.1.0.zip'

In your case [blender_folder] is 'C:\Users\Jim-2\AppData\Roaming\Blender Foundation\Blender'

 

Kind Regards.

 

 

When I run the bat file I get this error:

 

 

ERROR: The system was unable to find the specified registry key or value.

Traceback (most recent call last):

File "setup.py", line 2, in

from setuptools import setup

ImportError: No module named setuptools

Press any key to continue . . .

 

 

 

 

Link to comment

 

When I run the bat file I get this error:

 

 

ERROR: The system was unable to find the specified registry key or value.

Traceback (most recent call last):

File "setup.py", line 2, in

from setuptools import setup

ImportError: No module named setuptools

Press any key to continue . . .

 

 

Then simpliest way will be de-install Blender via 'Programs and Features'. Delete 'C:\Users\Jim-2\AppData\Roaming\Blender Foundation\'.

And install Blender again to be sure all pathes and registry entries are correct.

 

Kind Regards.

Link to comment

Thanks to Tweens with post and to gsll for keeping me still interested with this work ;)
Quick fix for work with baking - eliminated restriction to use only 'LocRot' keyframes.
Not tested myself in-game, but exporting to .kf was successful. I tried 'Pose->Animation->Bake Action...' with 'Only Selected' and 'Visual Keying' are checked.
NOTES:
1. Anyway, first frame for animated bone must have Location and Rotation data. Seems baking always do that. Maybe I'm wrong...
2. Scaling f-curve's data simply ignored.
3. Acton name restriction is removed, but anyway must be ONE action per skeleton.
Bug reports are very-very-welcome.
If script works OK, I'll try to find solution to reduce .kf size with not exporting unnecessary entries. For example if animation has 60 frames, .kf has 60 equal each other Translation Keys too, or if bone some time stays in rest, but all Rotation Keys in this range are duplicated.

 

Unpack in '\io_nifdata\animation\' with replacement.
bake_fix.7z

 

Kind Regards.

Link to comment

To vpoteryaev :

I have downloaded your new import script.

I will take a look.

 

My wrestling project seems out of reach ATM.

It requires advanced rigging to be efficient.

I need to try and succeed more simple things before.

I think a script that issues a custom rig out of an imported skeleton (similar to anton custom rig) should be a reachable target.

 

Should be :

- DEF bones : imported skeleton on which mesh will be skinned (*)

- IK bones : custom bones for IK chains,

- FK bones : custom bones for FK,

- IK/FK switch based on drivers and bones so that a rig can be copy/pasted without loss (or so I expect)

- mechanism bones to ease some complex movements.

 

In the end, only DEF bones have to be exported (or so it seems in Skyrim).

 

For now, I have studied the anton custom rig and started to gather information about rigging and scripting.

and started to build a custom rig without scripting.

 

I hope to come up with something to show within the week.

 

Best regards

 

(*) rotation constraint should be implemented on this one and weight painted accordingly.

For example, rotation along bone axis of UpperArmtwist1 , and UpperArmtwist2 should be an half of rotation along axis of UpperArm to avoid "bad twisting".

post-151375-0-50289400-1489478228_thumb.jpg

 

 

Link to comment
  • 1 month later...

So I contacted vpoteryaev about the flickering issue and he replied:

I don't have enough free time to create new anims myself and with it catch bugs in nif-utils.

Functionality uses blender's nif-plugin algorithm. I adapt it to modern versions only. With some improvements to allow copy-paste between instances without loosing anything.

I didn't create anims in 2.49 but seems this jerking/fleckering must happens too. When I created nif-utils and catch this issue, i just used T-pose and rotate one thigh left-right to pass z-axis. At first i thought it's my fault. Then i downloaded 'anton animations tools' and did same things. Result was exactly the same (I'm just curious: why nobody noticed it?). Then i dig into resulting .kf and noticed quaternion's 'switch'.

In your video i noticed this jerk only once in second loop and it's not really noticeable if passing z-axis are not too often.

Seems there is no common solution for this issue - at least for me. I'm not animator or too enough skilled in high mathematics (about 20 years passed when i studied in university).

Maybe sometimes 'my solution' must be turned off? Or realated to 'particular' bones? Just open in any text-editor '2.78\scripts\addons\io_nifdata\animation\export_data.py'. Locate lines:

                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
                    quat.negate()

They about 210-211 numbers and put in '#' to BEGINNING of lines:

                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#                   quat.negate()
                    prev_quat = quat
                    rot_frame.value.w = quat.w
                rot_frame.value.x = quat.x

Same things must be done with 'frame-by-frame' part, lines 276:

#vlk test with quaternion's vector don't jump over 90 degrees
                quat = Quaternion((rot_curve[frame].w, rot_curve[frame].x, rot_curve[frame].y, rot_curve[frame].z))
#                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#                    self.nif_export.dbg("bone {}, frame {} found jump".format(bone.name, frame))
#                    self.nif_export.dbg("prev {}\ncurr {}".format(prev_quat.axis, quat.axis))
#                    quat.negate()
                prev_quat = quat

Be carefull, Python is sensitive to 'space' and 'TAB' symbols (even i'm programmer, i really HATE this language with his stupid 'tabulating' format rules and not strictly assigned to types variables... LOL, i'm going away...). DO NOT use 'Enter', 'Space', 'TAB' on keyboard, just put '#'s.

Save file, launch Blender.

 

Kind Regards

 

 

Video I linked him:

 

*It "flickers" right as "ROOT COM" (the bone I'm oscillating here, but it occurs with all bones) passes through a certain orientation.

 

 

From what I can understand through his reply, he thinks that his quaternion-flip check might sometimes need to be skipped; however, even after commenting out those bits, the flicker still occurs. Further, I experimented by typing in a bunch of gibberish that I was sure would spit out an error somewhere.

 

#vlk test with quaternion's vector don't jump over 90 degrees
    quat = Quaternion((rot_curve[frame].w, rot_curve[frame].x, rot_curve[frame].y, rot_curve[frame].z))
#   if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#	self.nif_export.dbg("bone {}, frame {} found jump".format(bone.name, frame))
#	self.nif_export.dbg("prev {}\ncurr {}".format(prev_quat.axis, quat.axis))
#	quat.negate()
    afafafafakfgdjsagd
    djiosajgoidjsa
    there's no way that the interpreter can
    compile this ifjdoisajfg;idas320q5039809
    0195ui093ut09asi98v[9538a908f05302ai9tj3poiajtpoidsakfpod6546468465841fd685sa41f58484f843864a864f83a46
    prev_quat = quat

 

 

 

Yet to my surprise, it managed a perfectly usable .kf that I converted to .hkx and tested without a problem (except for the fact that it still flickered). Seeing as how it didn't error, I might have put the script in the wrong directory where it isn't being used at all. Can anyone confirm? I put the plugin inside:

...Blender 2.78\2.78\scripts\addons

 

and the "patched" export_data.py into:

...Blender 2.78\2.78\scripts\addons\io_nifdata\animation

 

"Blender 2.78" is the root folder that contains the launch executable. I export using frame-by-frame and I bake the action beforehand.

 

EDIT: If someone were to point me in the right direction for where the plugin outputs debug information, that'd be great.

 

EDIT2: Turns out, a restart of blender is required whenever a plugin script is changed. Commenting out the quaternion flipping fixed the flickering from NPC COM rotating on global Y. Gonna test with other rotations later.

Link to comment

 

 

So I contacted vpoteryaev about the flickering issue and he replied:

I don't have enough free time to create new anims myself and with it catch bugs in nif-utils.

Functionality uses blender's nif-plugin algorithm. I adapt it to modern versions only. With some improvements to allow copy-paste between instances without loosing anything.

I didn't create anims in 2.49 but seems this jerking/fleckering must happens too. When I created nif-utils and catch this issue, i just used T-pose and rotate one thigh left-right to pass z-axis. At first i thought it's my fault. Then i downloaded 'anton animations tools' and did same things. Result was exactly the same (I'm just curious: why nobody noticed it?). Then i dig into resulting .kf and noticed quaternion's 'switch'.

In your video i noticed this jerk only once in second loop and it's not really noticeable if passing z-axis are not too often.

Seems there is no common solution for this issue - at least for me. I'm not animator or too enough skilled in high mathematics (about 20 years passed when i studied in university).

Maybe sometimes 'my solution' must be turned off? Or realated to 'particular' bones? Just open in any text-editor '2.78\scripts\addons\io_nifdata\animation\export_data.py'. Locate lines:

                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
                    quat.negate()

They about 210-211 numbers and put in '#' to BEGINNING of lines:

                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#                   quat.negate()
                    prev_quat = quat
                    rot_frame.value.w = quat.w
                rot_frame.value.x = quat.x

Same things must be done with 'frame-by-frame' part, lines 276:

#vlk test with quaternion's vector don't jump over 90 degrees
                quat = Quaternion((rot_curve[frame].w, rot_curve[frame].x, rot_curve[frame].y, rot_curve[frame].z))
#                if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#                    self.nif_export.dbg("bone {}, frame {} found jump".format(bone.name, frame))
#                    self.nif_export.dbg("prev {}\ncurr {}".format(prev_quat.axis, quat.axis))
#                    quat.negate()
                prev_quat = quat

Be carefull, Python is sensitive to 'space' and 'TAB' symbols (even i'm programmer, i really HATE this language with his stupid 'tabulating' format rules and not strictly assigned to types variables... LOL, i'm going away...). DO NOT use 'Enter', 'Space', 'TAB' on keyboard, just put '#'s.

Save file, launch Blender.

 

Kind Regards

 

 

Video I linked him:

 

*It "flickers" right as "ROOT COM" (the bone I'm oscillating here, but it occurs with all bones) passes through a certain orientation.

 

 

From what I can understand through his reply, he thinks that his quaternion-flip check might sometimes need to be skipped; however, even after commenting out those bits, the flicker still occurs. Further, I experimented by typing in a bunch of gibberish that I was sure would spit out an error somewhere.

 

#vlk test with quaternion's vector don't jump over 90 degrees
    quat = Quaternion((rot_curve[frame].w, rot_curve[frame].x, rot_curve[frame].y, rot_curve[frame].z))
#   if degrees(abs(prev_quat.axis.angle(quat.axis))) > 90:
#	self.nif_export.dbg("bone {}, frame {} found jump".format(bone.name, frame))
#	self.nif_export.dbg("prev {}\ncurr {}".format(prev_quat.axis, quat.axis))
#	quat.negate()
    afafafafakfgdjsagd
    djiosajgoidjsa
    there's no way that the interpreter can
    compile this ifjdoisajfg;idas320q5039809
    0195ui093ut09asi98v[9538a908f05302ai9tj3poiajtpoidsakfpod6546468465841fd685sa41f58484f843864a864f83a46
    prev_quat = quat

 

 

 

Yet to my surprise, it managed a perfectly usable .kf that I converted to .hkx and tested without a problem (except for the fact that it still flickered). Seeing as how it didn't error, I might have put the script in the wrong directory where it isn't being used at all. Can anyone confirm? I put the plugin inside:

...Blender 2.78\2.78\scripts\addons

 

and the "patched" export_data.py into:

...Blender 2.78\2.78\scripts\addons\io_nifdata\animation

 

"Blender 2.78" is the root folder that contains the launch executable. I export using frame-by-frame and I bake the action beforehand.

 

EDIT: If someone were to point me in the right direction for where the plugin outputs debug information, that'd be great.

 

EDIT2: Turns out, a restart of blender is required whenever a plugin script is changed. Commenting out the quaternion flipping fixed the flickering from NPC COM rotating on global Y. Gonna test with other rotations later.

 

 

 

Here little update that allows to disable my 'solution' for quaternion jumping in export dialog. So you don't need waste time to edit scripts and restore backups. Just overwrite existing files.

It will be very helpfull if 'jumps' for particular bones were tested. Then I will add checks for that bones and don't use 'solution' for them directly in script. Or will add text-property like 'Moved Bones' where bones that don't require 'jump' check are listed.

 

Kind Regards

 

switch_option_update.7z

 

UPDATED:

By the way, debug info you can view in Blender's internal 'Text Editor' with 'Nif_IO_Debug' named.

Link to comment

I still don't understand why disabling what is supposed to "fix" the flipping fixed the flipping... Well after a few more animation tests I couldn't reproduce the flickering so I'm just going to leave it as is and hope it stays that way.

 

Hopefully that update will help others in the future. Thanks for this amazing plugin.  :lol:

 

EDIT: Adjectives.

Link to comment

Version 1.00 beta.
Added functionality to import animations from .kf file. I didn't perform tests but with a pair tries I got correct 'mt_idle' in blender.
To use:
1. goto 'File->Import->Skyrim nif-format Data (.nif)'.
2. in left file-select panel choose .nif with skeleton
3. Choose "Import skeleton"
4. In '.kf file' window type name with extension, for example 'mt_idle.kf'. Animation file and skeletion file MUST be placed AT SAME DIRECTORY!
5. Choose import.
6. After that a body may be attached like. 'File-Import....' again, clear '.kf file' window, choose 'Import Body' and select .nif.
7. When done, select imported body, "Alt-P"->'Clear Parent'. Delete in outliner useless now 'Scene Root', add Armature Modifier to imported body with selecting imported with animation skeleton.
8. Repeat step 7 for hands, e.t.c.

Sorry, but for now i have no time to make more user-friendly inerface, but will do someday.

Again, bug-reports are very welcome!!!

Kind Regards.
 

Link to comment

I found some time with testing.
I don't know what to do with non-uniform scaling. Seems most of 3DsMax-created animations have this warning in hkxcmd, and not accepted by my plug-in.
I never used 3dxMax, and tools for them and can't understand scaling jumping around 1.0. All vanilla animations have no this issue.
As example here a mix of my 'strip_boots' animation with wolf's 'aggrowarning1.hkx'. No problems.
What do you think? Even scaling is unnatural, maybe will add they handling?
 

post-436640-0-25977900-1494335901_thumb.jpg

post-436640-0-78804700-1494335962_thumb.jpg

wolf_aggrowarning1_strip_boots_mix.blend.7z

Kind Regards.

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. For more information, see our Privacy Policy & Terms of Use