Advertisement

Planning on using Blender

Started by March 16, 2017 05:10 PM
16 comments, last by BBeck 7 years, 8 months ago

Oh, does D3DXMesh still exists ?

Nope. The D3DX library was not maintained after D3D9. It's used by the example code for D3D9 only, it's not a "real" part of DirectX.

In addition to what Hodgman said, I believe they moved a lot of the functionality out to the DirectX Took Kit. Looks to me like they took a lot of that stuff out between DX10 and DX11 including Sprite and Model support. I think they did DXTK as a way to give it back to those who wanted it. I believe a lot of pro-game developers were basically writing their own anyway and they wanted to offload it.

I haven't tried DXTK myself. When I was doing DX11, I was bound and determined to figure out how to do it all myself. So, I built my own model class, exporter, and importer. Then I serialized the class to save the binary data out to disk. I would have gone on to make it support skinned animation. I got as far as doing a test run using XNA to play back Blender humanoid animation data as stick figures, but then decided to start doing OpenGL instead and had to start all over learning OGL. Then I got side tracked again with learning 3D modeling. Learning Vulkan is on my agenda but really before any of that I have to get my new computer built as the parts have been sitting here collecting dust since Christmas.

I never used D3DXMesh directly. I think what I was doing in XNA years ago was calling it to get the job done behind the scenes.

There's also ASSIMP for models although I don't know exactly how much it does for you since I haven't tried it. I've thought about trying to work ASSIMP into my OGL engine rather than rewriting my DX model class to support OGL. I can see some advantages to both and so I'm still not sure which direction I'll go with that if I ever get the time.

I actually have a bit of deprecated code in my DX11 engine. Some of it is probably because I wrote it for Windows 7 and MS no longer really supports that wanting everyone to use Win10. Apparently, there's no "good" way to get keyboard input in DX11 and hasn't been in DX for a long time. I'm using DX8 code to communicate with the Keyboard rather than going through the event loop. I think some of the error handling was deprecated code as well. I tried to avoid anything deprecated, but there seemed no good way to do some things in DX11 for Win7 without using deprecated code.

So, I'm guessing you could actually include D3DXMesh in DX11 or DX12 code.

Really, all a model is is a vertex buffer and an index buffer. The hard part is done in the modeling software to build all those vertices and assign them data. I made mine to import sub-meshes so that the model could be in different parts. That's mostly to support rigid animation, so that the parts can be animated separately. But I put it all in a single vertex buffer.

If you support skinned animation, it gets quite a bit more complex. You have to have all the skinning data such as vertex groups and weighting information to know how much each vertex is assigned to each bone in the armature. And you have to have the armature data itself (bones), which is a bit different from the sub-meshes having their own matrices in rigid animation. Then of course, there's all the animation data for the armature and calculating frames between the key frames.

I'm not sure if D3DXMesh supported animation. I'm betting it did because I seem to remember doing a tutorial once where I got a model to animate back in the DX9 days and back then I had no clue what I was doing. In fact, I failed to learn DX9 after a few years of effort. XNA came along and that's when I actually started figuring everything out and in XNA the model class did not natively support skinned animation. Then I went into DX11 without ever really learning DX9.

Advertisement

Agreed with what most people are saying here with the two main points.

  • Blender is cost effective and produces similar results (has a great community and lots of plugins).
  • Using Blender solely for that format is perhaps not the best use since it is not commonly used now.

Learn to create games through our vibrant platform of easy-to-follow video training material. Getting recognition of the knowledge and skills you gain from the courses is essential. We can provide you with globally recognised City & Guilds accredited certificates.

www.polygoncollege.com

Thanks for the reply`s

For the toolkit i see no download for XP & Win7, maybe i stay with old trusty DX9,

only it would be very handy to make stuff myself, i might understand things better for optimizing.

That means i have to make a blender export plugin, i bet there are enough examples for that in C.

I use vertexbuffer for the LevelMesh, only indexbuffer i dont know exact how it works, it seems i need it for the models.

And skinned animation is something i would like, only i dont wanto get involved in these seperate shader files for animations,

i want everything done in 1 source code file, not learn a new shader language on top, i dont know if that is possible ?

S T O P C R I M E !

Visual Pro 2005 C++ DX9 Cubase VST 3.70 Working on : LevelContainer class & LevelEditor

I think you have to use Python to write a Blender exporter. If you find a way to do it in C, let me know, because I pretty much hate Python. Then again, I only learned enough Python to write a Blender exporter. So, I imagine my code has plenty of room for improvement. But here is my Blender Python model data exporter:

import bpy


def ProcessChildren(f, ParentMesh, VerticesInModel, FacesInModel):  #Get all data for sub-meshes.
    VerticesSoFar = VerticesInModel
    FacesSoFar = FacesInModel
    NumberOfChildren = len(ParentMesh.children)
    if NumberOfChildren > 0:
        for ChildMesh in ParentMesh.children:
            HasUVCoordinates = ChildMesh.data.uv_layers.active
            HasVertexColors = ChildMesh.data.vertex_colors.active
            CountOfVertices = 0
            f.write("Name:%s\n" % ChildMesh.name)
            f.write("Parent:%s\n" % ChildMesh.parent.name)
            VerticesSoFar = VerticesSoFar + len(ChildMesh.data.vertices)
            ChildMesh.data.update(calc_tessface=True)
            FacesSoFar = FacesSoFar + len(ChildMesh.data.tessfaces)
            #Materials
            SubMeshMaterialNo = 0
            for Material in ChildMesh.material_slots:
                f.write("M:%d" % SubMeshMaterialNo)
                f.write("-%s" % Material.name)
                f.write(" T:%s" % Material.material.active_texture.image.name)
                f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
            #WorldMatrix
            WorldMatrixRowNumber = 0
            for WorldMatrixRow in ChildMesh.matrix_world.row:
                f.write("WMR%d" % WorldMatrixRowNumber)
                f.write(":%s\n" % str(tuple(WorldMatrixRow)))
                WorldMatrixRowNumber = WorldMatrixRowNumber + 1
            #Faces.
            FaceCount = 0
            for Face in ChildMesh.data.polygons:
                f.write("F:%d" % FaceCount)
                f.write(" M:%s" % str(Face.material_index))
                f.write(" N:({:f}".format(Face.normal[0]))
                f.write(",{:f}".format(Face.normal[1]))
                f.write(",{:f})".format(Face.normal[2]))
                f.write(" S:%s\n" % str(Face.use_smooth)[0])
                FaceCount = FaceCount + 1
                for Vert, Loop in zip(Face.vertices, Face.loop_indices):
                    f.write("P:%s" % str(tuple(ChildMesh.data.vertices[Vert].co)))
                    if HasUVCoordinates is not None:
                        f.write(", U:%s" % str(tuple(ChildMesh.data.uv_layers.active.data[Loop].uv)))
                    else:
                        f.write(", U:(0.0,0.0)")
                    f.write(", N:%s" % str(tuple(ChildMesh.data.vertices[Vert].normal)))
                    if HasVertexColors is not None:
                        f.write(", C:%s" % str(tuple(ChildMesh.data.vertex_colors.active.data[Vert].color)))
                    else:
                        f.write(", C:(0.0,0.0,0.0,0.0)")
                    f.write("\n")
            #Call child's children.
            VerticesSoFar, FacesSoFar = ProcessChildren(f, ChildMesh, VerticesSoFar, FacesSoFar)
    return VerticesSoFar, FacesSoFar

def write_some_data(context, filepath):
    HasUVCoordinates = bpy.context.active_object.data.uv_layers.active
    HasVertexColors = bpy.context.active_object.data.vertex_colors.active
    print("Exporting data...")
    bpy.context.active_object.data.update(calc_tessface=True)         #calc_tessface=True must be set before working with faces.
    
    f = open(filepath, 'w', encoding='utf-8')
    if bpy.context.active_object != None and bpy.context.active_object.parent == None and bpy.context.active_object.type == 'MESH':
        CountOfVertices = 0
        NumberOfMaterialsUsed = 0
        FacesInModel = 0
        VerticesInModel = len(bpy.context.active_object.data.vertices)
        FacesInModel = len(bpy.context.active_object.data.tessfaces)
        f.write("Punc!It Text\n")
        f.write("Rigid Animation\n")
        f.write("Name:%s\n" % bpy.context.active_object.name)
        f.write("Parent:None\n")
        #Materials
        MaterialNo = 0
        for Material in bpy.context.active_object.material_slots:
            f.write("M:%d" % MaterialNo)
            f.write("-%s" % Material.name)
            f.write(" T:%s" % Material.material.active_texture.image.name)
            f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
        #WorldMatrix
        WorldMatrixRowNumber = 0
        for WorldMatrixRow in bpy.context.active_object.matrix_world.row:
            f.write("WMR%d" % WorldMatrixRowNumber)
            f.write(":%s\n" % str(tuple(WorldMatrixRow)))
            WorldMatrixRowNumber = WorldMatrixRowNumber + 1
        #Faces.
        FaceCount = 0
        for Face in bpy.context.active_object.data.polygons:
            f.write("F:%d" % FaceCount)
            f.write(" M:%s" % str(Face.material_index))
            f.write(" N:({:f}".format(Face.normal[0]))
            f.write(",{:f}".format(Face.normal[1]))
            f.write(",{:f})".format(Face.normal[2]))
            f.write(" S:%s\n" % str(Face.use_smooth)[0])
            FaceCount = FaceCount + 1
            for Vert, Loop in zip(Face.vertices, Face.loop_indices):
                f.write("P:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].co)))
                if HasUVCoordinates is not None:
                    f.write(", U:%s" % str(tuple(bpy.context.active_object.data.uv_layers.active.data[Loop].uv)))
                else:
                    f.write(", U:(0.0,0.0)")
                f.write(", N:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].normal)))
                if HasVertexColors is not None:
                    f.write(", C:%s" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[Vert].color)))
                else:
                    f.write(", C:(0.0,0.0,0.0,0.0)")
                f.write("\n")
        #Children.
        VerticesInModel, FacesInModel = ProcessChildren(f, bpy.context.active_object, VerticesInModel, FacesInModel)
        #Footer
        f.write("Total Unique Vertices:%d\n" % VerticesInModel)
        f.write("Total Faces:%d\n" % FacesInModel)
        f.write("Total Materials:%d" % NumberOfMaterialsUsed)
    else:
        f.write("You must select the root mesh before exporting the model!")
    f.close()
    
    return {'FINISHED'}


# ExportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator


class ExportSomeData(Operator, ExportHelper):
    """This appears in the tooltip of the operator and in the generated docs"""
    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Export Button"

    # ExportHelper mixin class uses this
    filename_ext = ".txt"

    filter_glob = StringProperty(
            default="*.txt",
            options={'HIDDEN'},
            )

    def execute(self, context):
        return write_some_data(context, self.filepath)


# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
    self.layout.operator(ExportSomeData.bl_idname, text="Custom Exporter Test")


def register():
    bpy.utils.register_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.append(menu_func_export)


def unregister():
    bpy.utils.unregister_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.remove(menu_func_export)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.export_test.some_data('INVOKE_DEFAULT')

This is a toy car model I made in Blender and exported. This is what the output looks like:

Punc!It Text
Rigid Animation
Name:CarBody
Parent:None
M:0-CarMaterial T:SimplifiedCarBody.png C:(1.0, 1.0, 1.0)
WMR0:(1.0, 0.0, 0.0, 0.0)
WMR1:(0.0, 1.0, 0.0, 0.0)
WMR2:(0.0, 0.0, 1.0, 0.0)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-0.000000,-1.000000,0.000000) S:F
P:(0.6159690022468567, -1.0, 1.3930187225341797), U:(0.38228708505630493, 0.8303871154785156), N:(0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(1.0, 1.0, 0.0)
P:(-0.6159691214561462, -0.9999999403953552, 1.3930187225341797), U:(0.6177127957344055, 0.8303872346878052), N:(-0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(0.9686274528503418, 1.0, 0.003921568859368563)
P:(-0.6159691214561462, -0.9999999403953552, 0.6069812774658203), U:(0.617712676525116, 0.9806004762649536), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(1.0, 1.0, 0.0)
P:(0.6159690022468567, -1.0, 0.6069812774658203), U:(0.3822869658470154, 0.9806003570556641), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.9333333373069763, 1.0, 0.04313725605607033)
F:1 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.6159690618515015, 0.01772703416645527, 0.9793898463249207), U:(0.8122022747993469, 0.9094325304031372), N:(-0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(-0.6159690022468567, 0.7281867861747742, 1.0621156692504883), U:(0.9479727745056152, 0.8936232924461365), N:(-0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(-0.6159690022468567, 1.0, 0.6069812774658203), U:(0.9999170303344727, 0.9806004762649536), N:(-0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(0.929411768913269, 1.0, 0.0)
P:(-0.6159690618515015, 0.1418156772851944, 0.6069812774658203), U:(0.8359159827232361, 0.9806005954742432), N:(-0.7070833444595337, 0.0, -0.7070833444595337), C:(0.9333333373069763, 1.0, 0.05098039284348488)
F:2 M:0 N:(0.000000,0.858546,0.512737) S:F
P:(-0.6159690022468567, 0.7281867861747742, 1.0621156692504883), U:(0.5792591571807861, 0.008944153785705566), N:(-0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(0.6159691214561462, 0.7281866669654846, 1.0621156692504883), U:(0.5792591571807861, 0.2862038016319275), N:(0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.0)
P:(0.6159691214561462, 0.9999999403953552, 0.6069812774658203), U:(0.45994994044303894, 0.28620368242263794), N:(0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(1.0, 1.0, 0.0)
P:(-0.6159690022468567, 1.0, 0.6069812774658203), U:(0.45994997024536133, 0.008944228291511536), N:(-0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(0.929411768913269, 1.0, 0.0)
F:3 M:0 N:(1.000000,-0.000000,-0.000000) S:F
P:(0.6159690618515015, 0.017726941034197807, 0.9793898463249207), U:(0.18779747188091278, 0.9094322323799133), N:(0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.0)
P:(0.6159690022468567, -1.0, 1.3930187225341797), U:(0.38228708505630493, 0.8303871154785156), N:(0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(1.0, 1.0, 0.0)
P:(0.6159690022468567, -1.0, 0.6069812774658203), U:(0.3822869658470154, 0.9806003570556641), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.9333333373069763, 1.0, 0.04313725605607033)
P:(0.6159690618515015, 0.14181558787822723, 0.6069812774658203), U:(0.16408395767211914, 0.9806002378463745), N:(0.7070833444595337, 0.0, -0.7070833444595337), C:(1.0, 1.0, 0.0)
F:4 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.6159690618515015, 0.14181558787822723, 0.6069812774658203), U:(0.2668073773384094, 0.28620344400405884), N:(0.7070833444595337, 0.0, -0.7070833444595337), C:(1.0, 1.0, 0.0)
P:(-0.6159690618515015, 0.1418156772851944, 0.6069812774658203), U:(0.2668076157569885, 0.008944153785705566), N:(-0.7070833444595337, 0.0, -0.7070833444595337), C:(0.9333333373069763, 1.0, 0.05098039284348488)
P:(-0.6159690022468567, 1.0, 0.6069812774658203), U:(0.45994997024536133, 0.008944228291511536), N:(-0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(0.929411768913269, 1.0, 0.0)
P:(0.6159691214561462, 0.9999999403953552, 0.6069812774658203), U:(0.45994994044303894, 0.28620368242263794), N:(0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(1.0, 1.0, 0.0)
F:5 M:0 N:(0.000000,0.376516,0.926410) S:F
P:(0.6159690618515015, 0.017726941034197807, 0.9793898463249207), U:(0.7402355074882507, 0.28620395064353943), N:(0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.0)
P:(-0.6159690618515015, 0.01772703416645527, 0.9793898463249207), U:(0.740235447883606, 0.008944094181060791), N:(-0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(-0.6159691214561462, -0.9999999403953552, 1.3930187225341797), U:(0.9874796867370605, 0.008944094181060791), N:(-0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(0.9686274528503418, 1.0, 0.003921568859368563)
P:(0.6159690022468567, -1.0, 1.3930187225341797), U:(0.9874798059463501, 0.28620395064353943), N:(0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(1.0, 1.0, 0.0)
F:6 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.6159691214561462, -0.9999999403953552, 1.3930187225341797), U:(0.6177127957344055, 0.8303872346878052), N:(-0.5597094893455505, -0.46266061067581177, 0.6874599456787109), C:(0.9686274528503418, 1.0, 0.003921568859368563)
P:(-0.6159690618515015, 0.01772703416645527, 0.9793898463249207), U:(0.8122022747993469, 0.9094325304031372), N:(-0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(-0.6159690618515015, 0.1418156772851944, 0.6069812774658203), U:(0.8359159827232361, 0.9806005954742432), N:(-0.7070833444595337, 0.0, -0.7070833444595337), C:(0.9333333373069763, 1.0, 0.05098039284348488)
P:(-0.6159691214561462, -0.9999999403953552, 0.6069812774658203), U:(0.617712676525116, 0.9806004762649536), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(1.0, 1.0, 0.0)
F:7 M:0 N:(1.000000,-0.000000,-0.000000) S:F
P:(0.6159691214561462, 0.7281866669654846, 1.0621156692504883), U:(0.052026983350515366, 0.8936232924461365), N:(0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.0)
P:(0.6159690618515015, 0.017726941034197807, 0.9793898463249207), U:(0.18779747188091278, 0.9094322323799133), N:(0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.0)
P:(0.6159690618515015, 0.14181558787822723, 0.6069812774658203), U:(0.16408395767211914, 0.9806002378463745), N:(0.7070833444595337, 0.0, -0.7070833444595337), C:(1.0, 1.0, 0.0)
P:(0.6159691214561462, 0.9999999403953552, 0.6069812774658203), U:(8.296234591398388e-05, 0.9806005954742432), N:(0.5541856288909912, 0.7238990664482117, -0.4108401834964752), C:(1.0, 1.0, 0.0)
F:8 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.6159690022468567, -1.0, 0.6069812774658203), U:(0.009831011295318604, 0.2862032651901245), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.9333333373069763, 1.0, 0.04313725605607033)
P:(-0.6159691214561462, -0.9999999403953552, 0.6069812774658203), U:(0.00983119010925293, 0.008943945169448853), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(1.0, 1.0, 0.0)
P:(-0.6159690618515015, 0.1418156772851944, 0.6069812774658203), U:(0.2668076157569885, 0.008944153785705566), N:(-0.7070833444595337, 0.0, -0.7070833444595337), C:(0.9333333373069763, 1.0, 0.05098039284348488)
P:(0.6159690618515015, 0.14181558787822723, 0.6069812774658203), U:(0.2668073773384094, 0.28620344400405884), N:(0.7070833444595337, 0.0, -0.7070833444595337), C:(1.0, 1.0, 0.0)
F:9 M:0 N:(-0.000000,-0.115658,0.993289) S:F
P:(0.6159691214561462, 0.7281866669654846, 1.0621156692504883), U:(0.5792591571807861, 0.2862038016319275), N:(0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.0)
P:(-0.6159690022468567, 0.7281867861747742, 1.0621156692504883), U:(0.5792591571807861, 0.008944153785705566), N:(-0.6028626561164856, 0.35294654965400696, 0.7155064344406128), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(-0.6159690618515015, 0.01772703416645527, 0.9793898463249207), U:(0.740235447883606, 0.008944094181060791), N:(-0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.003921568859368563)
P:(0.6159690618515015, 0.017726941034197807, 0.9793898463249207), U:(0.7402355074882507, 0.28620395064353943), N:(0.7674794793128967, 0.08630634844303131, 0.635181725025177), C:(0.929411768913269, 1.0, 0.0)
Name:WheelBkPort
Parent:CarBody
M:0-BackPortMaterial T:SimplifiedCarFrontPort.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, -0.9599999785423279)
WMR1:(0.0, 1.0, 0.0, -1.0)
WMR2:(0.0, 0.0, 1.0, 0.30000001192092896)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-0.000000,-1.000000,0.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(1.0000817775726318, 0.4998322129249573), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.750124990940094, 0.4998321533203125), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7501248121261597, 0.2498754858970642), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(1.0000817775726318, 0.24987530708312988), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:1 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.750124990940094, 0.4998321533203125), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.5001685619354248, 0.4998323321342468), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.5001682043075562, 0.24987581372261047), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7501248121261597, 0.2498754858970642), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:2 M:0 N:(0.000000,1.000000,0.000000) S:F
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.5001685619354248, 0.4998323321342468), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.2502121329307556, 0.49983274936676025), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.2502116858959198, 0.24987617135047913), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.5001682043075562, 0.24987581372261047), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
F:3 M:0 N:(1.000000,-0.000000,0.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.2502121329307556, 0.49983274936676025), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.0002555549144744873, 0.49983328580856323), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.0002550482749938965, 0.24987667798995972), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.2502116858959198, 0.24987617135047913), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:4 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(1.0000817775726318, 0.24987530708312988), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7501248121261597, 0.2498754858970642), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.7501246929168701, -8.171796798706055e-05), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(1.0000818967819214, -8.183717727661133e-05), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:5 M:0 N:(0.000000,-0.000000,1.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(1.0000817775726318, 0.7497890591621399), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.750124990940094, 0.7497889399528503), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.750124990940094, 0.4998321533203125), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(1.0000817775726318, 0.4998322129249573), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
Name:WheelBkStarboard
Parent:CarBody
M:0-BackStarboardMaterial T:SimplifiedCarFrontPort.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, 0.949999988079071)
WMR1:(0.0, 1.0, 0.0, -1.0)
WMR2:(0.0, 0.0, 1.0, 0.30000001192092896)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-0.000000,-1.000000,0.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(1.0009549856185913, 0.49895909428596497), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.7509981393814087, 0.4989590346813202), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7509979009628296, 0.2490023672580719), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(1.0009549856185913, 0.24900218844413757), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:1 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.7509981393814087, 0.4989590346813202), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.5010417103767395, 0.4989592134952545), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.5010412931442261, 0.24900269508361816), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7509979009628296, 0.2490023672580719), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:2 M:0 N:(0.000000,1.000000,0.000000) S:F
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.5010417103767395, 0.4989592134952545), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.2510852813720703, 0.49895963072776794), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.2510848045349121, 0.24900305271148682), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.5010412931442261, 0.24900269508361816), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
F:3 M:0 N:(1.000000,-0.000000,0.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.2510852813720703, 0.49895963072776794), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.0011286735534667969, 0.4989601671695709), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.001128166913986206, 0.2490035593509674), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.2510848045349121, 0.24900305271148682), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:4 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(1.0009549856185913, 0.24900218844413757), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7509979009628296, 0.2490023672580719), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.75099778175354, -0.0009548366069793701), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(1.0009549856185913, -0.0009549558162689209), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:5 M:0 N:(0.000000,-0.000000,1.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(1.0009549856185913, 0.7489159107208252), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.7509981393814087, 0.7489157915115356), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.7509981393814087, 0.4989590346813202), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(1.0009549856185913, 0.49895909428596497), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
Name:WheelFtPort
Parent:CarBody
M:0-FrontPortMaterial T:SimplifiedCarFrontPort.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, -0.9599999785423279)
WMR1:(0.0, 1.0, 0.0, 0.9999998211860657)
WMR2:(0.0, 0.0, 1.0, 0.30000001192092896)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-0.000000,-1.000000,0.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.25004422664642334, 0.25004151463508606), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.5000007748603821, 0.2500423192977905), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.5000001788139343, 0.49999886751174927), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.2500433921813965, 0.49999815225601196), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:1 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.5000007748603821, 0.2500423192977905), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.7499570846557617, 0.2500428855419159), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.7499568462371826, 0.4999992251396179), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.5000001788139343, 0.49999886751174927), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:2 M:0 N:(0.000000,1.000000,0.000000) S:F
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.7499570846557617, 0.2500428855419159), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.9999133348464966, 0.2500429153442383), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.999913215637207, 0.49999916553497314), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.7499568462371826, 0.4999992251396179), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
F:3 M:0 N:(1.000000,-0.000000,0.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(8.738040924072266e-05, 0.2500404715538025), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.25004422664642334, 0.25004151463508606), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.2500433921813965, 0.49999815225601196), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(8.654594421386719e-05, 0.49999719858169556), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:4 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.9999133944511414, 0.749955415725708), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.7499570846557617, 0.7499555945396423), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.7499568462371826, 0.4999992251396179), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.999913215637207, 0.49999916553497314), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:5 M:0 N:(0.000000,-0.000000,1.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.9999133348464966, 0.2500429153442383), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.7499570846557617, 0.2500428855419159), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.7499572038650513, 8.666515350341797e-05), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.9999133944511414, 8.678436279296875e-05), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
Name:FtPortPropeller
Parent:WheelFtPort
M:0-FrontPortPropelerMaterial T:SimplifiedCarFrontPortProp.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, -1.25)
WMR1:(0.0, 1.0, 0.0, 1.0)
WMR2:(0.0, 0.0, 1.0, 0.3333300054073334)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.501366138458252, 0.5319569706916809), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.05822812020778656, 0.5319639444351196), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.05822690576314926, 0.4211801588535309), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.5013640522956848, 0.42117220163345337), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:1 M:0 N:(0.000000,1.000000,-0.000000) S:F
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.05822812020778656, 0.5319639444351196), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.0028362085577100515, 0.5319638848304749), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.0028361277654767036, 0.4211793541908264), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.05822690576314926, 0.4211801588535309), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:2 M:0 N:(1.000000,0.000000,-0.000000) S:F
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.9999024271965027, 0.5319446325302124), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.5567590594291687, 0.531956136226654), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.5567563772201538, 0.4211706221103668), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.999899685382843, 0.4211588203907013), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:3 M:0 N:(0.000000,-1.000000,0.000000) S:F
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.5567590594291687, 0.531956136226654), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.501366138458252, 0.5319569706916809), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.5013640522956848, 0.42117220163345337), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.5567563772201538, 0.4211706221103668), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:4 M:0 N:(-0.000000,0.000000,-1.000000) S:F
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.0554872564971447, 9.955011773854494e-05), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.05822690576314926, 0.4211801588535309), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.0028361277654767036, 0.4211793541908264), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(9.761026012711227e-05, 9.761026012711227e-05), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:5 M:0 N:(-0.000000,0.000000,1.000000) S:F
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.005591780412942171, 0.953059732913971), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.0028362085577100515, 0.5319638848304749), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.05822812020778656, 0.5319639444351196), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.060983531177043915, 0.9530596733093262), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
Name:WheelFtStarboard
Parent:CarBody
M:0-FrontStarboardMaterial T:SimplifiedCarFrontPort.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, 0.949999988079071)
WMR1:(0.0, 1.0, 0.0, 1.0)
WMR2:(0.0, 0.0, 1.0, 0.30000001192092896)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-0.000000,-1.000000,0.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.7499573230743408, 0.25004249811172485), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.9999132752418518, 0.25004273653030396), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.999913215637207, 0.49999862909317017), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.7499569654464722, 0.4999988079071045), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:1 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(8.830868318909779e-05, 0.2500384449958801), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.2500448524951935, 0.2500401735305786), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.2500433325767517, 0.49999675154685974), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(8.658744627609849e-05, 0.4999949634075165), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:2 M:0 N:(0.000000,1.000000,0.000000) S:F
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.2500448524951935, 0.2500401735305786), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.5000011920928955, 0.250041663646698), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.5000001192092896, 0.4999980628490448), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.2500433325767517, 0.49999675154685974), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
F:3 M:0 N:(1.000000,-0.000000,0.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.5000011920928955, 0.250041663646698), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.7499573230743408, 0.25004249811172485), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.7499569654464722, 0.4999988079071045), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.5000001192092896, 0.4999980628490448), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:4 M:0 N:(0.000000,-0.000000,-1.000000) S:F
P:(0.29999998211860657, -0.30000004172325134, -0.30000001192092896), U:(0.7499569654464722, 0.4999988079071045), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, -0.30000001192092896), U:(0.999913215637207, 0.49999862909317017), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, -0.30000001192092896), U:(0.9999135136604309, 0.7499545216560364), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.11372549086809158, 0.003921568859368563, 1.0)
P:(0.30000004172325134, 0.29999998211860657, -0.30000001192092896), U:(0.7499575614929199, 0.7499548196792603), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
F:5 M:0 N:(0.000000,-0.000000,1.000000) S:F
P:(0.30000004172325134, 0.29999998211860657, 0.30000001192092896), U:(0.7499576210975647, 8.658744627609849e-05), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.29999998211860657, 0.30000004172325134, 0.30000001192092896), U:(0.9999135136604309, 8.686506771482527e-05), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
P:(-0.30000004172325134, -0.29999998211860657, 0.30000001192092896), U:(0.9999132752418518, 0.25004273653030396), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.12941177189350128, 0.0235294122248888, 1.0)
P:(0.29999998211860657, -0.30000004172325134, 0.30000001192092896), U:(0.7499573230743408, 0.25004249811172485), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.10980392247438431, 0.0, 1.0)
Name:FtStarboardPropeller
Parent:WheelFtStarboard
M:0-FrontStarboardPropMaterial T:SimplifiedCarFrontPortProp.png C:(0.800000011920929, 0.800000011920929, 0.800000011920929)
WMR0:(1.0, 0.0, 0.0, 1.25)
WMR1:(0.0, 1.0, 0.0, 1.0)
WMR2:(0.0, 0.0, 1.0, 0.3333300054073334)
WMR3:(0.0, 0.0, 0.0, 1.0)
F:0 M:0 N:(-1.000000,0.000000,0.000000) S:F
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.9997372627258301, 0.5350660681724548), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.5566012263298035, 0.5350320935249329), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.5566093921661377, 0.42424821853637695), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.999745786190033, 0.4242819547653198), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:1 M:0 N:(0.000000,1.000000,-0.000000) S:F
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.5566012263298035, 0.5350320935249329), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.501209557056427, 0.5350278615951538), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.5012171864509583, 0.4242442846298218), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.5566093921661377, 0.42424821853637695), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:2 M:0 N:(1.000000,0.000000,-0.000000) S:F
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.501209557056427, 0.5350278615951538), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.05807733163237572, 0.5349979400634766), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.05808385834097862, 0.42421552538871765), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.5012171864509583, 0.4242442846298218), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:3 M:0 N:(0.000000,-1.000000,0.000000) S:F
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.05807733163237572, 0.5349979400634766), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.0026867054402828217, 0.5349938869476318), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.0026956163346767426, 0.4242139160633087), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.05808385834097862, 0.42421552538871765), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:4 M:0 N:(-0.000000,0.000000,-1.000000) S:F
P:(-0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.0026956163346767426, 0.4242139160633087), N:(-0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(-5.901232361793518e-05, 0.0031646303832530975), N:(-0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, -0.05000000074505806), U:(0.055326636880636215, 0.0031646303832530975), N:(0.5773491859436035, 0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, -0.20000000298023224, -0.05000000074505806), U:(0.05808385834097862, 0.42421552538871765), N:(0.5773491859436035, -0.5773491859436035, -0.5773491859436035), C:(0.0,0.0,0.0,0.0)
F:5 M:0 N:(-0.000000,0.000000,1.000000) S:F
P:(0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.05807733163237572, 0.5349979400634766), N:(0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.06080096587538719, 0.956089973449707), N:(0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, 0.20000000298023224, 0.05000000074505806), U:(0.005409713834524155, 0.9560858607292175), N:(-0.5773491859436035, 0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
P:(-0.02500000037252903, -0.20000000298023224, 0.05000000074505806), U:(0.0026867054402828217, 0.5349938869476318), N:(-0.5773491859436035, -0.5773491859436035, 0.5773491859436035), C:(0.0,0.0,0.0,0.0)
Total Unique Vertices:60
Total Faces:46
Total Materials:0

There is no advantage to exporting to a binary format unless that binary format can be loaded straight into your data types, which at the very least would require a much greater knowledge of Python. What you really want to do is load your model class with this data and then serialize it so that the binary model file perfectly matches your model class data and thus is most efficient for loading into the model class to load a model. So, whatever you export, it's probably going to get converted; so it might as well be human readable.

This format is similar in some ways to the OBJ format which might be a good one to learn as well.

I called this file format the PUNC file format for Position, UV, Normal, Color as that's the data in the vertices. The first line allows you to verify that it is a PUNC file. The second line identifies the type of PUNC file as I was planning on a separate format for skinned animation from the rigid animation format. Then it goes into a loop of model parts/meshes. The first line in the loop is the sub-mesh name which in this case is the body of the car. If the sub-mesh has a parent because it was parented in Blender the second line in the loop will identify which sub-mesh is it's parent. (I believe there are two ways to parent something in Blender and one works for this and the other doesn't, but I can't remember off the top of my head what that is.) The CarBody has no parent, which makes it the root mesh and it will be the parent of all the others (which are wheels).

The next line identifies the material used for the sub-mesh. I think this allows multiple materials per sub-mesh assigning each a number starting from 0. Then the T identifies any texture image file used for that material and C identifies any color used for the entire material.

After that it has the WMR lines. This is a world/object matrix for the sub-mesh. I think WMR stood for "World Matrix Row". It's just a 4 by 4 world matrix. These matrices are the relative positions and offsets of each sub-mesh from each other as assigned in Blender. In this case, this positions the wheels relative to the car body. And the body is an identity matrix basically placing it at the world origin.

Then it goes into another sub-loop describing "faces". This is going to use a triangle list rather than a triangle strip or triangle fan. So, it's basically a list of triangles. But Blender basically does things in faces rather than in triangles. So, the first face has four vertices. You have to figure out how to break this up into triangles. I assume all Blender faces have co-planar triangles, which means it should not matter how you assign the edges to triangulate the face. I usually triangulate the model in Blender before exporting. I've only tested this format a little and so there may still be some bugs. I think the most complicated model I tested with was Blender's Suzanne monkey.

But for each face it gives the material number which references the texture and color at the beginning. Then it defines a face normal. And I think the S value was for flat shading or smooth shading allowing some faces to be smooth and others faceted in the same sub-mesh. As I get better at modeling, I am appreciating that more. Then it's a vertex list of all the vertices in that face, their positions, UV coordinates, vertex normals, and colors. Note that you may not always use all of these values. UV coordinates and vertex colors are often mutually exclusive. You tend to use one or the other, but not both. You can use both, which is why it's like this. But usually you either use a texture or vertex colors and not both at the same time.

So, then it just repeats that loop going through every face of the sub-mesh and expecting you to break the faces up into triangles. The list ends when you hit the name of the next sub-mesh. I don't think the sub-meshes are in parent-child order and so you may have to read them in and then figure out which is the parent and which is the child.

The file ends when it lists the "Total Unique Vertices". Looks like that total number of materials is broken. I don't think I actually used those last 3 lines when reading the data back in. But that's basically all there is to it. It allows you to build a vertex buffer. And there's enough info there to build an index buffer if you want. My code loads the entire model and all its sub-meshes into a single vertex buffer and then uses offsets in the buffer for each sub-mesh.


In my C++ code, I used two classes for the model. I have a Model Compiler class that reads this file and I have a RigidModel class that it reads the data into. The model class looks like this:

RigidModel.h

#pragma once
#include <d3d11.h>
#include <DirectXMath.h>
#include <DxErr.h>
#include <vector>        //NOT actual vectors. These are dynamic arrays.
#include "TextureClass.h"
#include "ShaderClass.h"

struct PUNCVERTEX{ DirectX::XMFLOAT3 Position; DirectX::XMFLOAT2 UV; DirectX::XMFLOAT3 Normal; DirectX::XMFLOAT4 Color; };    //Describes the structure of our vertices.


//__declspec(align(16)) class MeshPart
class MeshPart
{
public:
    MeshPart();
    ~MeshPart();
    void Shutdown();
    void AddChild(MeshPart* Child);
    void Draw(ID3D11DeviceContext* GraphicsDeviceContext, ID3D11Buffer* VertexBuffer, ID3D11Buffer* IndexBuffer,
        DirectX::CXMMATRIX View, DirectX::CXMMATRIX Projection, ShaderClass Shader, XMFLOAT3 DiffuseLightDirection,
        XMFLOAT4 AmbientLightColor, XMFLOAT4 DiffuseLightColor, DirectX::CXMMATRIX FamilyWorld);
    std::string Name;
    DirectX::XMFLOAT4X4 World;
    unsigned int FirstVertexInBuffer;
    unsigned int FirstIndexInBuffer;
    unsigned int VerticesInThisMeshPart;
    unsigned int IndicesInThismeshPart;
    TextureClass* Texture;
    std::vector<MeshPart*> Children;
};


class RigidModel
{
public:
    RigidModel();
    ~RigidModel();
    bool RigidModel::BuildModelFromBuffer(PUNCVERTEX* VertexArray, int VerticesInModel,
        int* IndexArray, int IndicesInModel,
        ID3D11Device* GraphicsDevice, ID3D11DeviceContext* GraphicsDeviceContext);
    void Draw(ID3D11DeviceContext* GraphicsDeviceContext, CXMMATRIX View, CXMMATRIX Projection, ShaderClass Shader,
        XMFLOAT3 DiffuseLightDirection, XMFLOAT4 AmbientLightColor, XMFLOAT4 DiffuseLightColor);
    void Shutdown();
    std::string Name;
    MeshPart Root;
private:
    int VerticesInMesh;                            //Number of vertices used in the mesh.
    int IndicesInMesh;                            //Number of indices used in the index buffer.
    ID3D11Buffer* VertexBuffer;                 //The pointer to the vertex buffer
    ID3D11Buffer* IndexBuffer;                    //The pointer to the index buffer.
};

RigidModel.cpp]/b]

#include "RigidModel.h"


RigidModel::RigidModel()
{
}


RigidModel::~RigidModel()
{
    Shutdown();
}


bool RigidModel::BuildModelFromBuffer(PUNCVERTEX* VertexArray, int VerticesInModel,
    int* IndexArray, int IndicesInModel,
    ID3D11Device* GraphicsDevice, ID3D11DeviceContext* GraphicsDeviceContext)
{
    D3D11_BUFFER_DESC VertexBufferDescription;                //The settings for the vertex buffer.
    D3D11_SUBRESOURCE_DATA VertexBufferSubResourceData;        //How a sub-resource is to be
    D3D11_BUFFER_DESC IndexBufferDescription;                //The settings for the index buffer.
    D3D11_SUBRESOURCE_DATA IndexBufferSubResourceData;        //How a sub-resource is to be
    bool ModelCreatedSuccessfully = false;


    if (VertexBuffer == nullptr)    //Don't try and create a vertex buffer for the object if it's already created.
    {
        VerticesInMesh = VerticesInModel;                                            //We might want this info later so remember it.
        ZeroMemory(&VertexBufferDescription, sizeof(VertexBufferDescription));        //Initialize memory to zeros.
        VertexBufferDescription.Usage = D3D11_USAGE_DYNAMIC;                        //Read-write access type for CPU and GPU
        VertexBufferDescription.ByteWidth = sizeof(PUNCVERTEX) * VerticesInMesh;    //Total size of the vertex buffer.
        VertexBufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;                //Buffer is a vertex buffer.
        VertexBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;            //Allow CPU to write in buffer.

        VertexBufferSubResourceData.pSysMem = VertexArray;
        VertexBufferSubResourceData.SysMemPitch = NULL;
        VertexBufferSubResourceData.SysMemSlicePitch = NULL;


        if (SUCCEEDED(GraphicsDevice->CreateBuffer(&VertexBufferDescription, &VertexBufferSubResourceData, &VertexBuffer)))    //Create the vertex buffer or stop if it fails.
        {
            IndicesInMesh = IndicesInModel;
            ZeroMemory(&IndexBufferDescription, sizeof(IndexBufferDescription));
            IndexBufferDescription.Usage = D3D11_USAGE_DEFAULT;
            IndexBufferDescription.ByteWidth = sizeof(int) * IndicesInMesh;            //Total size of the index buffer.
            IndexBufferDescription.BindFlags = D3D11_BIND_INDEX_BUFFER;            //Buffer is an index buffer.
            IndexBufferDescription.CPUAccessFlags = NULL;    
            IndexBufferDescription.MiscFlags = NULL;


            IndexBufferSubResourceData.pSysMem = IndexArray;
            IndexBufferSubResourceData.SysMemPitch = NULL;
            IndexBufferSubResourceData.SysMemSlicePitch = NULL;
            if (SUCCEEDED(GraphicsDevice->CreateBuffer(&IndexBufferDescription, &IndexBufferSubResourceData, &IndexBuffer)))    //Create the vertex buffer or stop if it fails.
            {
                ModelCreatedSuccessfully = true;
            }
        }
    }

    return ModelCreatedSuccessfully;
}


void RigidModel::Shutdown()
{
    if (VertexBuffer != nullptr)
    {
        VertexBuffer->Release();
        VertexBuffer = nullptr;
    }

    Root.Shutdown();
}

void RigidModel::Draw(ID3D11DeviceContext* GraphicsDeviceContext, DirectX::CXMMATRIX View, DirectX::CXMMATRIX Projection, ShaderClass Shader,
    XMFLOAT3 DiffuseLightDirection, XMFLOAT4 AmbientLightColor, XMFLOAT4 DiffuseLightColor)
{
    Root.Draw(GraphicsDeviceContext, VertexBuffer, IndexBuffer, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor, DirectX::XMMatrixIdentity());
}

MeshPart::MeshPart()
{
    XMStoreFloat4x4(&World, DirectX::XMMatrixIdentity());
    Name.clear();
    Texture = nullptr;
    FirstVertexInBuffer = 0;
    VerticesInThisMeshPart = 0;
    IndicesInThismeshPart = 0;
}

MeshPart::~MeshPart()
{
    Shutdown();
}


void MeshPart::Shutdown()
{
    //Shutdown all children.
    for (auto Child : Children)
    {
        Child->Shutdown();
        //_aligned_free(Child);
        delete Child;
        Child = nullptr;
    }
    Children.clear();
    //Then Shutdown self.
    if (Texture != nullptr)
    {
        delete Texture;
        Texture = nullptr;
    }
}


void MeshPart::AddChild(MeshPart* Child)
{
    Children.push_back(Child);
}


void MeshPart::Draw(ID3D11DeviceContext* GraphicsDeviceContext, ID3D11Buffer* VertexBuffer, ID3D11Buffer* IndexBuffer,
    DirectX::CXMMATRIX View, DirectX::CXMMATRIX Projection, ShaderClass Shader,    XMFLOAT3 DiffuseLightDirection,
    XMFLOAT4 AmbientLightColor, XMFLOAT4 DiffuseLightColor, DirectX::CXMMATRIX FamilyWorld)
{
    UINT Stride = sizeof(PUNCVERTEX);    //Stride is the size of 1 vertex in memory.
    UINT Offset = 0;
    UINT IndexOffset = 0;
    DirectX::XMMATRIX RelationalWorld;

    RelationalWorld = XMLoadFloat4x4(&World) * FamilyWorld;    //This makes the submesh's world matrix relative to its parent which is relevant to its parent and so on.
    if (Texture == nullptr)
    {
        Shader.Settings(GraphicsDeviceContext, RelationalWorld, View, Projection, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor, nullptr, 0.0f);
    }
    else
    {
        Shader.Settings(GraphicsDeviceContext, RelationalWorld, View, Projection, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor, Texture->ResourceView(), 2.0f);
    }
    //Offset = FirstVertexInBuffer * sizeof(PUNCVERTEX);        //Offset is in bytes. FirstVertexInBuffer is in vertices.
    //IndexOffset = FirstIndexInBuffer * sizeof(int);
    GraphicsDeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, &Stride, &Offset);    //Select which vertex buffer to display.
    GraphicsDeviceContext->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, IndexOffset);
    GraphicsDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);    //Select which primtive type we are using.
    GraphicsDeviceContext->DrawIndexed(IndicesInThismeshPart, FirstIndexInBuffer, FirstVertexInBuffer);        //Not using DrawIndexed. Draw the Bottom.


    if (Children.size() > 0)
    {
        for (auto Child : Children)
        {
            Child->Draw(GraphicsDeviceContext, VertexBuffer, IndexBuffer, View, Projection, Shader, DiffuseLightDirection, AmbientLightColor, DiffuseLightColor, RelationalWorld);
        }
    }
}

And this class loads the data into the RigidModel class from the Python export:

ModelCompiler.h

#pragma once
#include <fstream>
#include <sstream>
#include "RigidModel.h"
#include "StringConversions.h"


class Face
{
public:
    int CountVertices();
    int CountTriangles();
    Face();
    Face(std::string Header);
    void AddVertex(std::string CodedVertexString);
    PUNCVERTEX GetVertex(int VertexNumber);
private:
    unsigned int Number;
    unsigned int MaterialNumber;
    DirectX::XMFLOAT3 FaceNormal;
    bool SmoothShaded;
    std::vector<PUNCVERTEX> VerticesInFace;
};


class Material
{
public:
    Material();
    //Material(int No, std::string TextureFile, DirectX::XMFLOAT4 RGBColor);
    int Number;
    std::string Name;
    std::string Texture;
    DirectX::XMFLOAT4 Color;
};


class MeshPiece
{
public:
    std::string Name;
    std::string Parent;
    DirectX::XMFLOAT4X4 World;
    std::vector<Material> Materials;
    std::vector<PUNCVERTEX> Vertices;
    std::vector<Face> Faces;
    std::vector<PUNCVERTEX> MeshPiece::GetVertices();
private:
    void GetVerticesFromFaces();
};


class ModelCompiler
{
public:
    ModelCompiler();
    ~ModelCompiler();
    bool Build(RigidModel &Model, std::string FileName, ID3D11Device* GraphicsDevice, ID3D11DeviceContext* GraphicsDeviceContext);
    bool CreateModel(RigidModel &Model, std::vector<MeshPiece> SubMeshList, std::string TexturesFolder, ID3D11Device* GraphicsDevice,
        ID3D11DeviceContext* GraphicsDeviceContext);
    bool SaveToDisk(RigidModel &ModelToSave, PUNCVERTEX* VertexArray, int VerticesInModel, int* IndexArray, int IndicesInModel);
private:
    std::vector<MeshPiece> SubMeshes;
    Material CreateMaterial(std::string UnparsedText);
    void GetChildren(MeshPart* Parent, std::vector<PUNCVERTEX> &VertexBufferBuildList,
        std::vector<int> &IndexBufferBuildList, int &NumberOfVerticesAdded, int &NumberOfIndicesAdded,
        std::vector<MeshPiece>, std::string TexturesFolder, ID3D11Device* GraphicsDevice);
    void GetModelBuffers(PUNCVERTEX* &VertexBufferPtr, int &TotalNumberOfVertices,
        int* &IndexBufferPtr, int &TotalNumberOfIndices, std::vector<PUNCVERTEX> &VertexList);
    void GetPartBuffers(std::vector<PUNCVERTEX> &PartVertices, std::vector<PUNCVERTEX> &VertexBufferBuildList,
        std::vector<int> &IndexBufferBuildList, int &NumberOfVerticesAdded, int &NumberOfIndicesAdded);
    bool VerticesAreEqual(PUNCVERTEX A, PUNCVERTEX B);
    void SaveChildrenToDisk(int NumberOfChildren, MeshPart &Part, std::ofstream &ModelFile);
};

ModelCompiler.cpp

#include "ModelCompiler.h"


ModelCompiler::ModelCompiler()
{
}


ModelCompiler::~ModelCompiler()
{
    //Free all the memory we allocated for the submeshes.
    for (auto Part : SubMeshes)
    {
        delete &Part;
    }
}


bool ModelCompiler::Build(RigidModel &Model, std::string FileName, ID3D11Device* GraphicsDevice, ID3D11DeviceContext* GraphicsDeviceContext)
{
    bool ModelCreatedSuccessfully = false;
    bool LoadedCorrectly = false;
    StringConversions StringConverter;
    std::ifstream InputFile(FileName);
    std::string LineOfText;
    unsigned int LineNumber = 0;
    MeshPiece* SubMesh = nullptr;
    std::string MatrixRow1 = "";
    std::string MatrixRow2 = "";
    std::string MatrixRow3 = "";
    


    std::getline(InputFile, LineOfText);
    if (LineOfText == "Punc!It Text")
    {
        //LineNumber++;
        std::getline(InputFile, LineOfText);
        if (LineOfText == "Rigid Animation")
        {
            //LineNumber++;
            std::getline(InputFile, LineOfText);
            while (!InputFile.eof())
            {
                if (LineOfText.substr(0, 5) == "Name:")
                {
                    if (SubMesh != nullptr) SubMeshes.push_back(*SubMesh);        //Every time you read a name it is a new submesh in the model so store the one just built.
                    SubMesh = new MeshPiece();                                //Start to build a new submesh.
                    SubMesh->Name = LineOfText.substr(5, LineOfText.length() - 5);    //Get the name of the submesh.
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 2) == "P:")
                {
                    //Line should already be processed as part of face, so just ignore it and go on.
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 2) == "F:")
                {
                    Face NewFace(LineOfText);
                    std::getline(InputFile, LineOfText);
                    while (LineOfText.substr(0, 2) == "P:")
                    {
                        NewFace.AddVertex(LineOfText);
                        std::getline(InputFile, LineOfText);
                    }
                    SubMesh->Faces.push_back(NewFace);
                }
                else if (LineOfText.substr(0, 2) == "M:")
                {
                    Material NewMaterial;
                    NewMaterial = CreateMaterial(LineOfText);
                    SubMesh->Materials.push_back(NewMaterial);
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 5) == "WMR0:")
                {
                    MatrixRow1 = LineOfText;
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 5) == "WMR1:")
                {
                    MatrixRow2 = LineOfText;
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 5) == "WMR2:")
                {
                    MatrixRow3 = LineOfText;
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 5) == "WMR3:")
                {
                    DirectX::XMStoreFloat4x4(&SubMesh->World, StringConverter.StringsToMatrix(MatrixRow1, MatrixRow2, MatrixRow3, LineOfText));
                    MatrixRow1.clear(); MatrixRow2.clear(); MatrixRow3.clear();
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 7) == "Parent:")
                {
                    SubMesh->Parent = LineOfText.substr(7, LineOfText.size() - 7);
                    std::getline(InputFile, LineOfText);
                }
                else if (LineOfText.substr(0, 22) == "Total Unique Vertices:")
                {
                    if (SubMesh != nullptr) SubMeshes.push_back(*SubMesh);    //EoF so a new Name: line will not be reached but we still need to save the submesh.
                    std::getline(InputFile, LineOfText);
                }
                else std::getline(InputFile, LineOfText);
            }
            InputFile.close();
            int LastSlash = FileName.find_last_of("/");
            int FileExtensionStart = FileName.find(".txt");
            Model.Name = FileName.substr(LastSlash + 1, FileExtensionStart - LastSlash -1);

            ModelCreatedSuccessfully = CreateModel(Model, SubMeshes, "./Models/", GraphicsDevice, GraphicsDeviceContext);
        }
    }
    return ModelCreatedSuccessfully;
}


Material ModelCompiler::CreateMaterial(std::string UnparsedText)
{
    Material NewMaterial;
    StringConversions StringConverter;
    std::vector<std::string> Delimiters;
    std::vector<std::string> ParsedStrings;
    std::string ColorValues;

    Delimiters.push_back("M:");
    Delimiters.push_back("-");
    Delimiters.push_back("T:");
    Delimiters.push_back("C:(");
    Delimiters.push_back(")");
    StringConverter.Parse(UnparsedText, Delimiters, ParsedStrings, true);
    Delimiters.clear();

    NewMaterial.Number = std::stoi(ParsedStrings[0]);
    NewMaterial.Name = ParsedStrings[1];
    NewMaterial.Texture = ParsedStrings[2];
    ColorValues = ParsedStrings[3];
    Delimiters.push_back(",");
    ParsedStrings.clear();
    StringConverter.Parse(ColorValues, Delimiters, ParsedStrings, false);
    NewMaterial.Color.x = std::stof(ParsedStrings[0]);    //Red
    NewMaterial.Color.y = std::stof(ParsedStrings[1]);    //Green
    NewMaterial.Color.z = std::stof(ParsedStrings[2]);    //Blue
    NewMaterial.Color.w = 1.0f;    //Set alpha to 100%. Blender does not export an alpha value.
    return NewMaterial;
}


bool ModelCompiler::CreateModel(RigidModel &Model, std::vector<MeshPiece> SubMeshList, std::string TexturesFolder, ID3D11Device* GraphicsDevice,
    ID3D11DeviceContext* GraphicsDeviceContext)
{
    bool ModelCreatedSuccessfully = false;
    std::vector<MeshPart> PartsTree;
    PUNCVERTEX* VertexBufferPtr = nullptr;
    int* IndexBufferPtr = nullptr;
    int NumberOfIndices = 0;
    int TotalNumberOfVertices = 0;
    int TotalNumberOfIndices = 0;
    std::vector<PUNCVERTEX> BuildList;
    std::vector<PUNCVERTEX> VertexList;
    std::vector<int> IndexList;
    int Root = -1;

    MeshPart* RootMeshPart = &Model.Root;
    std::vector<MeshPiece>::iterator MeshListIterator;
    TextureClass* NewTexture;
    bool ExitLoop = false;


    MeshListIterator = SubMeshList.begin();
    while (!ExitLoop)
    {
        
        if (MeshListIterator->Parent == "None")
        {
            Root = (int) (MeshListIterator - SubMeshList.begin());    //Store the index withing the vector to the root mesh of the model.
            ExitLoop = true;
        }
        if (MeshListIterator == SubMeshList.end()) ExitLoop = true;
            else MeshListIterator++;
    }
    
    RootMeshPart->Name = SubMeshList[Root].Name;
    RootMeshPart->World = SubMeshList[Root].World;
    if (SubMeshList[Root].Materials.size() > 0)    //No materials means there are no textures.
    {
        NewTexture = new TextureClass();
        NewTexture->Load(TexturesFolder + SubMeshList[Root].Materials[0].Texture, GraphicsDevice);    //Only handles 1 material. Probably need to change this.
        RootMeshPart->Texture = NewTexture;
    }
    RootMeshPart->FirstVertexInBuffer = 0;
    BuildList = SubMeshList[Root].GetVertices();
    
    GetPartBuffers(BuildList, VertexList, IndexList, TotalNumberOfVertices, TotalNumberOfIndices);
    
    RootMeshPart->VerticesInThisMeshPart = (int) TotalNumberOfVertices;
    RootMeshPart->IndicesInThismeshPart = (int)TotalNumberOfIndices;
    
    GetChildren(RootMeshPart, VertexList, IndexList, TotalNumberOfVertices, TotalNumberOfIndices, SubMeshList, TexturesFolder, GraphicsDevice);

    DirectX::XMMATRIX RotatedWorld;
    RotatedWorld = DirectX::XMLoadFloat4x4(&RootMeshPart->World);
    RotatedWorld *= DirectX::XMMatrixRotationX(-DirectX::XM_PIDIV2);    //Conversion to correct Blender world coordinate system difference to DX coordinate system.
    DirectX::XMStoreFloat4x4(&RootMeshPart->World, RotatedWorld);
    
    VertexBufferPtr = new PUNCVERTEX[TotalNumberOfVertices];
    IndexBufferPtr = new int[TotalNumberOfIndices];

    ZeroMemory(VertexBufferPtr, sizeof(PUNCVERTEX) * TotalNumberOfVertices);
    for (int VertexNumber = 0; VertexNumber < TotalNumberOfVertices; VertexNumber++)
    {
        VertexBufferPtr[VertexNumber] = VertexList[VertexNumber];
    }

    ZeroMemory(IndexBufferPtr, sizeof(int) * TotalNumberOfIndices);
    for (int IndexNumber = 0; IndexNumber < TotalNumberOfIndices; IndexNumber++)
    {
        IndexBufferPtr[IndexNumber] = IndexList[IndexNumber];
    }

    ModelCreatedSuccessfully = Model.BuildModelFromBuffer(VertexBufferPtr, TotalNumberOfVertices,
        IndexBufferPtr, TotalNumberOfIndices, GraphicsDevice, GraphicsDeviceContext);

    //Save Model to File.
    if (ModelCreatedSuccessfully)
        ModelCreatedSuccessfully = SaveToDisk(Model, VertexBufferPtr, TotalNumberOfVertices, IndexBufferPtr, TotalNumberOfIndices);

    delete[] VertexBufferPtr;    //Vertex buffer has been copied to an ID3D11Buffer and this array we allocated is no longer needed after that.
    VertexBufferPtr = nullptr;
    delete[] IndexBufferPtr;
    IndexBufferPtr = nullptr;

    return ModelCreatedSuccessfully;
}


bool ModelCompiler::SaveToDisk(RigidModel &ModelToSave, PUNCVERTEX* VertexArray, int VerticesInModel,
    int* IndexArray, int IndicesInModel)
{
    bool SavedProperly = false;
    //std::string ModelFileName = ModelToSave.Name;
    std::ofstream ModelFile;
    const char* FileID{"Rigid Model File"};

    ModelFile.open("CompiledModel.RMF", std::ios_base::binary);
    ModelFile.write(FileID, 16);
    ModelFile.write((char*)&VerticesInModel, sizeof(VerticesInModel));
    ModelFile.write((char*)VertexArray, sizeof(PUNCVERTEX)*VerticesInModel);
    ModelFile.write((char*)&IndicesInModel, sizeof(IndicesInModel));
    ModelFile.write((char*)IndexArray, sizeof(int)*IndicesInModel);
    ModelFile.write(ModelToSave.Name.c_str(), ModelToSave.Name.size()+1);    //Write the string with the null terminator.
    //Write Root.
    ModelFile.write(ModelToSave.Root.Name.c_str(), ModelToSave.Root.Name.size() + 1);    //Write root node name with the string null terminator.
    ModelFile.write((char*)&ModelToSave.Root.FirstVertexInBuffer, sizeof(unsigned int));
    ModelFile.write((char*)&ModelToSave.Root.VerticesInThisMeshPart, sizeof(unsigned int));
    ModelFile.write((char*)&ModelToSave.Root.FirstIndexInBuffer, sizeof(unsigned int));
    ModelFile.write((char*)&ModelToSave.Root.IndicesInThismeshPart, sizeof(unsigned int));
    ModelFile.write((char*)&ModelToSave.Root.World._11, sizeof(float));    //World Matrix.
    ModelFile.write((char*)&ModelToSave.Root.World._12, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._13, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._14, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._21, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._22, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._23, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._24, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._31, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._32, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._33, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._34, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._41, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._42, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._43, sizeof(float));
    ModelFile.write((char*)&ModelToSave.Root.World._44, sizeof(float));
    ModelFile.write(ModelToSave.Root.Texture->GetFileName().c_str(), ModelToSave.Root.Texture->GetFileName().size() + 1);
    int NumberOfChildren = ModelToSave.Root.Children.size();
    ModelFile.write((char*)&NumberOfChildren, sizeof(unsigned int));
    
    SaveChildrenToDisk(NumberOfChildren, ModelToSave.Root, ModelFile);

    ModelFile.close();    
    SavedProperly = true;

    return SavedProperly;
}


void ModelCompiler::SaveChildrenToDisk(int NumberOfChildren, MeshPart &Part, std::ofstream &ModelFile)
{
    if (NumberOfChildren > 0)
    {
        for (auto Child : Part.Children)
        {
            ModelFile.write(Child->Name.c_str(), Child->Name.size() + 1);    //Write the string with the null terminator.
            ModelFile.write((char*)&Child->FirstVertexInBuffer, sizeof(unsigned int));
            ModelFile.write((char*)&Child->VerticesInThisMeshPart, sizeof(unsigned int));
            ModelFile.write((char*)&Child->FirstIndexInBuffer, sizeof(unsigned int));
            ModelFile.write((char*)&Child->IndicesInThismeshPart, sizeof(unsigned int));
            ModelFile.write((char*)&Child->World._11, sizeof(float));    //World Matrix.
            ModelFile.write((char*)&Child->World._12, sizeof(float));
            ModelFile.write((char*)&Child->World._13, sizeof(float));
            ModelFile.write((char*)&Child->World._14, sizeof(float));
            ModelFile.write((char*)&Child->World._21, sizeof(float));
            ModelFile.write((char*)&Child->World._22, sizeof(float));
            ModelFile.write((char*)&Child->World._23, sizeof(float));
            ModelFile.write((char*)&Child->World._24, sizeof(float));
            ModelFile.write((char*)&Child->World._31, sizeof(float));
            ModelFile.write((char*)&Child->World._32, sizeof(float));
            ModelFile.write((char*)&Child->World._33, sizeof(float));
            ModelFile.write((char*)&Child->World._34, sizeof(float));
            ModelFile.write((char*)&Child->World._41, sizeof(float));
            ModelFile.write((char*)&Child->World._42, sizeof(float));
            ModelFile.write((char*)&Child->World._43, sizeof(float));
            ModelFile.write((char*)&Child->World._44, sizeof(float));
            ModelFile.write(Child->Texture->GetFileName().c_str(), Child->Texture->GetFileName().size() + 1);
            int NumberOfGrandChildren = Child->Children.size();
            ModelFile.write((char*)&NumberOfGrandChildren, sizeof(unsigned int));

            SaveChildrenToDisk(NumberOfGrandChildren, *Child, ModelFile);

        }
    }
}
 

bool ModelCompiler::VerticesAreEqual(PUNCVERTEX A, PUNCVERTEX B)
{
    return A.Position.x == B.Position.x
        && A.Position.y == B.Position.y
        && A.Position.z == B.Position.z
        && A.UV.x == B.UV.x
        && A.UV.y == B.UV.y
        && A.Normal.x == B.Normal.x
        && A.Normal.y == B.Normal.y
        && A.Normal.z == B.Normal.z
        && A.Color.x == B.Color.x
        && A.Color.y == B.Color.y
        && A.Color.z == B.Color.z
        && A.Color.w == B.Color.w;
}


void ModelCompiler::GetChildren(MeshPart* Parent, std::vector<PUNCVERTEX> &VertexBufferBuildList,
    std::vector<int> &IndexBufferBuildList, int &NumberOfVerticesAdded, int &NumberOfIndicesAdded,
    std::vector<MeshPiece> Meshs, std::string TexturesFolder, ID3D11Device* GraphicsDevice)
{
    std::vector<PUNCVERTEX> VerticesOfSubMesh;

    for (auto Mesh : Meshs)
    {
        if (Mesh.Parent == Parent->Name)
        {
            MeshPart* FoundChild = new MeshPart();
            FoundChild->Name = Mesh.Name;
            DirectX::XMMATRIX ParentsWorld = DirectX::XMLoadFloat4x4(&Parent->World);
            ParentsWorld = DirectX::XMMatrixInverse(nullptr, ParentsWorld);
            DirectX::XMMATRIX LocalWorld = DirectX::XMLoadFloat4x4(&Mesh.World);
            ParentsWorld = LocalWorld * ParentsWorld;
            DirectX::XMStoreFloat4x4(&FoundChild->World, ParentsWorld); //Multiplying by an inverse is basically subtracting one matrix from the other. Make children relative to parents.
    
            if (Mesh.Materials.size() > 0)
            {
                TextureClass* NewTexture = new TextureClass();
                NewTexture->Load(TexturesFolder + Mesh.Materials[0].Texture, GraphicsDevice);    //Only handles 1 material. Probably need to change this.
                FoundChild->Texture = NewTexture;
            }
            else FoundChild->Texture = nullptr;
            FoundChild->FirstVertexInBuffer = NumberOfVerticesAdded;
            FoundChild->FirstIndexInBuffer = NumberOfIndicesAdded;
            VerticesOfSubMesh = Mesh.GetVertices();

            GetPartBuffers(VerticesOfSubMesh, VertexBufferBuildList, IndexBufferBuildList, NumberOfVerticesAdded, NumberOfIndicesAdded);

            FoundChild->VerticesInThisMeshPart = NumberOfVerticesAdded - FoundChild->FirstVertexInBuffer;
            FoundChild->IndicesInThismeshPart = NumberOfIndicesAdded - FoundChild->FirstIndexInBuffer;

            GetChildren(FoundChild, VertexBufferBuildList, IndexBufferBuildList, NumberOfVerticesAdded,
                NumberOfIndicesAdded, Meshs, TexturesFolder, GraphicsDevice);

            Parent->AddChild(FoundChild);
            FoundChild = nullptr;
        }
    }
}


void ModelCompiler::GetPartBuffers(std::vector<PUNCVERTEX> &PartVertices, std::vector<PUNCVERTEX> &VertexBufferBuildList, std::vector<int> &IndexBufferBuildList,
    int &NumberOfVerticesAdded, int &NumberOfIndicesAdded)
{
    bool VertexFoundInList = false;
    int VertexFoundInPosition = -1;
    int NewPartIndex = 0;
    int IndicesPreviouslyAdded = NumberOfIndicesAdded;
    std::vector<PUNCVERTEX> TempBuildList;

    for (auto UnprocessedVertex : PartVertices)
    {
        //Find Vertex in VerticesOfSubMesh.
        int ListPosition = -1;

        //for (auto FinalVertex : VertexBufferBuildList)
        for (auto FinalVertex : TempBuildList)
        {
            ListPosition++;
            if (VerticesAreEqual(FinalVertex, UnprocessedVertex))
            {
                VertexFoundInList = true;
                VertexFoundInPosition = ListPosition;
            }
        }
        if (!VertexFoundInList)    //Not in the new list, add it.
        {
            VertexBufferBuildList.push_back(UnprocessedVertex);
            TempBuildList.push_back(UnprocessedVertex);
            IndexBufferBuildList.push_back(NewPartIndex);
            NumberOfVerticesAdded++;
            NumberOfIndicesAdded++;
            NewPartIndex++;
        }
        else    //In the new list already, just add its position to the index list.
        {
            IndexBufferBuildList.push_back(VertexFoundInPosition);
            NumberOfIndicesAdded++;
            VertexFoundInList = false;
        }
        VertexFoundInPosition = -1;
    }
}



std::vector<PUNCVERTEX> MeshPiece::GetVertices()
{
    Vertices.clear();
    GetVerticesFromFaces();
    return Vertices;
}


void MeshPiece::GetVerticesFromFaces()
{
    int NumberOfTrianglesInFace = 0;

    for (auto Polygon : Faces)
    {
        NumberOfTrianglesInFace = Polygon.CountTriangles();

        switch (NumberOfTrianglesInFace)
        {
            case 1:
                Vertices.push_back(Polygon.GetVertex(2));
                Vertices.push_back(Polygon.GetVertex(1));
                Vertices.push_back(Polygon.GetVertex(0));
                break;
            case 2:
                Vertices.push_back(Polygon.GetVertex(2));
                Vertices.push_back(Polygon.GetVertex(1));
                Vertices.push_back(Polygon.GetVertex(0));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(3));
                Vertices.push_back(Polygon.GetVertex(2));
                break;
            case 3:
                Vertices.push_back(Polygon.GetVertex(2));
                Vertices.push_back(Polygon.GetVertex(1));
                Vertices.push_back(Polygon.GetVertex(0));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(3));
                Vertices.push_back(Polygon.GetVertex(2));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(4));
                Vertices.push_back(Polygon.GetVertex(3));
                break;
            case 4:
                Vertices.push_back(Polygon.GetVertex(2));
                Vertices.push_back(Polygon.GetVertex(1));
                Vertices.push_back(Polygon.GetVertex(0));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(3));
                Vertices.push_back(Polygon.GetVertex(2));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(4));
                Vertices.push_back(Polygon.GetVertex(3));

                Vertices.push_back(Polygon.GetVertex(0));
                Vertices.push_back(Polygon.GetVertex(5));
                Vertices.push_back(Polygon.GetVertex(4));
                break;
            default:
                //Unhandled exception with too many triangles to count
                break;
        }
    }
}


Face::Face()
{
    Number = 0;
    MaterialNumber = 0;
    FaceNormal = DirectX::XMFLOAT3(0.f, 0.f, 0.f);
    SmoothShaded = false;
    VerticesInFace.clear();
}

Face::Face(std::string Header)
{
    StringConversions StringConverter;
    std::vector<std::string> Delimiters;
    std::vector<std::string> ParsedStrings;

    Delimiters.push_back("F:");
    Delimiters.push_back("M:");
    Delimiters.push_back("N:(");
    Delimiters.push_back(") S:");
    Delimiters.push_back(",");
    StringConverter.Parse(Header, Delimiters, ParsedStrings, true);
    Number = std::stoul(ParsedStrings[0]);
    MaterialNumber = std::stoul(ParsedStrings[1]);
    FaceNormal.x = std::stof(ParsedStrings[2]);
    FaceNormal.y = std::stof(ParsedStrings[3]);
    FaceNormal.z = std::stof(ParsedStrings[4]);
    if (ParsedStrings[5] == "T") SmoothShaded = true;
        else SmoothShaded = false;
}


void Face::AddVertex(std::string CodedVertexString)
{
    StringConversions StringConverter;
    std::vector<std::string> Delimiters;
    std::vector<std::string> ParsedStrings;
    PUNCVERTEX NewVertex;
    DirectX::XMFLOAT2 TempUV;
    DirectX::XMFLOAT3 Vec3To4;


    ZeroMemory(&NewVertex, sizeof(NewVertex));
    Delimiters.push_back("P:(");
    Delimiters.push_back("), U:(");
    Delimiters.push_back("), N:(");
    Delimiters.push_back("), C:(");

    StringConverter.Parse(CodedVertexString, Delimiters, ParsedStrings, true);
    NewVertex.Position = StringConverter.StringToVector3(ParsedStrings[0]);
    TempUV = StringConverter.StringToVector2(ParsedStrings[1]);        //Store UV coordinates to temp value because Blender has the V(which is y) value inversed.
    NewVertex.UV.x = TempUV.x;
    NewVertex.UV.y = 1.0f - TempUV.y;
    NewVertex.Normal = StringConverter.StringToVector3(ParsedStrings[2]);
    Vec3To4 = StringConverter.StringToVector3(ParsedStrings[3]);
    NewVertex.Color = DirectX::XMFLOAT4(Vec3To4.x, Vec3To4.y, Vec3To4.z, 1.0f);    //Could be a bug because not stipping ) at the end of line.

    VerticesInFace.push_back(NewVertex);
}


int Face::CountVertices()
{
    return (int) VerticesInFace.size();
}


int Face::CountTriangles()
{
    int FaceVertices = (int) VerticesInFace.size();
    int TrianglesInFace = 0;

    if (FaceVertices > 2)
    {
        if (FaceVertices < 7)   //There could be more but we'll limit it for now.
        {
            if (FaceVertices == 3) TrianglesInFace = 1;
            if (FaceVertices == 4) TrianglesInFace = 2;
            if (FaceVertices == 5) TrianglesInFace = 3;
            if (FaceVertices == 6) TrianglesInFace = 4;
        }
    }

    return TrianglesInFace;
}


PUNCVERTEX Face::GetVertex(int VertexNumber)
{
    return VerticesInFace[VertexNumber];
}

Material::Material(void){}

The entire project is on my website for download including the Python script and the textures for the model. The Python above is the abreviated version. The Python file in the project file has a bunch of other Python scripts that may prove useful in understanding the Blender data and how it is organized. I found getting info on the Blender data to be next to impossible. I actually "discovered" the Blender data layout through trial and error by just fishing around until I figured it out over a couple of months. Fortunately, Blender is really good about helping you on these fishing expeditions. Still, a lot of what's in the full Python file is stuff that I fished around and found and will likely be useful in figuring the layout of the data.

http://virtuallyprogramming.com/DirectX11/Tutorials/Tutorials.html

If I understood you right, you said you don't know how an index buffer works. It's pretty straight forward. The index buffer is just a list of which vertices to process in what order. This allows your vertices in your vertex buffer to be used out of order and multiple times. For example, a quad (rectangle) made up of two triangles, might have an edge where two of the vertices are identical in both triangles. They are shared vertices. So, instead of specifying 6 vertices for the two triangles you only have to specify 4 and two of them get re-used in both triangles.

In that case, your vertex buffer might looks something like: 0,1,2,2,1,4

The graphics card knows that every 3 vertices makes a triangle. So, the first triangle is 0,1,2 and the second is 2,1,4 where vertices 2 and 1 are used in both triangles. Then your vertex buffer only has 4 vertices instead of six making your vertex buffer a whole lot smaller and saving memory on the graphics card. For a 4 byte integer (I believe it is) you saved a vertex which in the PUNC case is something like 11 four byte floats I believe. It can save a huge amount of memory.

But all it really is is a list of which vertices to process in what order. Every 3 values is a triangle. At least, I believe that's the way it works with a Triangle List(It's been probably a year since I've written any graphics code). In a triangle strip, I believe every vertex is a new triangle and it uses the last two vertices defined to form the three sides of the triangle. In that case, all the triangles are connected by definition. So, it only takes one vertex (plus the previous two) to define a triangle. I would love to use triangle strips in my model (because they are substantially more efficient), but I doubt it's even possible. I gave up on that a long time ago and just use a triangle list.

Oh. Also be aware of your "winding". Back face culling will remove the backside of the triangle, if it is turned on. It determines which side is the backside by whether the vertices are defined clockwise or counter-clockwise. So, the order you define them in is important. You want back face culling on because it saves the graphics card from having to draw back faces that will never be seen by the camera such as the inside of an object. With an index buffer, you define your order using the index buffer. But index buffers are optional. Without an index buffer your order would be determined in the vertex buffer. Turn back face culling off for debugging, but otherwise you want it on.

Advertisement

Now that I think about it, some may find it useful to see my entire Python script collection. Like I said, the only way I could figure out Blender scripting was to just fish around and try things out. There was little to no instructions I could find on how Blender data is organized. These scripts are things I saved while fishing around that pulled certain types of data from Blender. I think there's some stuff in there for skinned animation as I see some references to armatures.

I wrote a program that extracted the animation data from Blender using the basic humanoid armature that is in Blender. I created the animations in Blender using the basic humanoid armature and then my script exported those animations to a text file. I then loaded the file into an XNA program where I played them back as stick figures. It worked. The stick figures moved just like the armatures in the Blender animations.

Looks like the code for that is on my website here:

http://virtuallyprogramming.com/XNATutorials/ThreeDTutorials/SecondTutorial/SecondTutorial.html

But it is an XNA project, not a DX project. Still, that should not matter if you are just interested in the Blender exporter. The Blender exporter should be the same regardless of whether it is XNA or DX. Wait, I was able to find what appears to be the Blender exporter to export the animations. I'll make that a separate post.

#Python scripts and code to output the model data and also experimenting.
#The final script in this file is the one used to produce the models for this NewFormat code.
bpy.data.objects['CarBody'].data.vertices[0].co
bpy.data.objects['CarBody'].data.vertices[0].normal
bpy.data.objects['CarBody'].data.vertices[0].index
bpy.data.objects['CarBody'].matrix_world


Must have "Textured Solid" selected in the "Shading" menu of the N-menu (Properties) to see colors.

bpy.context.active_object.name
bpy.context.active_object.type
bpy.context.active_object.type == 'MESH' #Verify selected object is a mesh rather than camera, etc.
bpy.context.active_object.active_material.name #Active Material is what's selected and not what the mesh uses.
len(bpy.data.materials) #Number of Materials Used.
bpy.data.materials[1].diffuse_color  #Color of material 1.
bpy.data.materials[0].name   #Name of Material Zero.
bpy.data.materials[0].use_textures[0]  #True or False.
bpy.data.materials[0].texture_slots['MyTexture'].texture.image.name
bpy.context.active_object.active_material.diffuse_color
bpy.context.active_object.data.vertices[0].co
bpy.context.active_object.data.vertex_colors.active.data[0].color
bpy.context.active_object.data.tessfaces[0].use_smooth    #smooth or flat shading.
bpy.data.objects['WheelFtPort'].data.materials[0].texture_slots[0].texture.image.name
bpy.context.active_object.active_material.texture_slots[0].texture.image


for clr in bpy.context.active_object.data.vertex_colors.active.data: print(clr.color)

bpy.context.active_object.children[3].data.tessfaces[0].material_index

#Material Index points back to the Material Slot # of the mesh?

##################################################################
ob = bpy.context.active_object


for face in ob.data.polygons:
                for vert, loop in zip(face.vertices, face.loop_indices):
                    for item in ob.data.vertices[vert].normal:  # normal
                        print("Normal: %d" % item)
                    for item in ob.data.vertices[vert].co:  # vertex
                        print("Vertex: %d" % item)
                    for item in (ob.data.uv_layers.active.data[loop].uv if ob.data.uv_layers.active is not None else (0.0, 0.0)):  # uv
                        print("UV: %d" % item)


##################################################################
# List Faces
for Face in bpy.context.active_object.data.polygons:
    for Vert, Loop in zip(Face.vertices, Face.loop_indices):
        print(Vert)
    print("\n")


# List Face UVs
for Face in bpy.context.active_object.data.polygons:
    for Vert, Loop in zip(Face.vertices, Face.loop_indices):
        print(str(tuple(bpy.context.active_object.data.uv_layers.active.data[Loop].uv)))
    print("\n")


# List Face PUNC
# Appears to be accurate, but greatly multiples the number of vertices.
for Face in bpy.context.active_object.data.polygons:
    for Vert, Loop in zip(Face.vertices, Face.loop_indices):
        print("P:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].co)))
        print("U:%s" % str(tuple(bpy.context.active_object.data.uv_layers.active.data[Loop].uv)))
        print("N:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].normal)))
        print("C:%s" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[Vert].color)))
    print("\n")


#print("X:%s" % str(tuple(bpy.context.active_object.data.uv_layers.active.data[Vert].uv))) #wrong


# List Face PUNC
# Appears to be accurate, but greatly multiples the number of vertices.
MatNo = 0
for Material in bpy.context.active_object.material_slots:
    print("M:", MatNo, " Name:", Material.name, " Texture:", Material.material.active_texture.name, " Image:", Material.material.active_texture.image.name)
    MatNo = MatNo + 1

for Face in bpy.context.active_object.data.polygons:
    print("Face Normal:", round(Face.normal[0],7), ",", round(Face.normal[1],7), ",", round(Face.normal[2],7))
    print("Face Normal:{:f}".format(Face.normal[0]), ",", "{:f}".format(Face.normal[1]), ",", "{:f}".format(Face.normal[2]))
    print("Face Normal:{0}".format(tuple(Face.normal)))
    print("Material:%d" % Face.material_index)
    for Vert, Loop in zip(Face.vertices, Face.loop_indices):
        Pos = str(tuple(bpy.context.active_object.data.vertices[Vert].co))
        UV = str(tuple(bpy.context.active_object.data.uv_layers.active.data[Loop].uv))
        Norm =str(tuple(bpy.context.active_object.data.vertices[Vert].normal))
        Col =str(tuple(bpy.context.active_object.data.vertex_colors.active.data[Vert].color))
        print("P:", Pos, " U:", UV, " N:", Norm, " C:", Col)
    print("\n")


#############################################################

#Count triangles
bpub
len(bpy.context.active_object.data.tessfaces)

#############################################################

#List vertices of each quad

for Face in bpy.context.active_object.data.polygons:
    for Vert, Loop in zip(Face.vertices, Face.loop_indices):
        print("Vertex:", Vert)
    print("Material:", Face.material_index)
#############################################################

#Another way to list the vertices of each quad
bpy.context.active_object.data.update(calc_tessface=True)
print(len(bpy.context.active_object.data.tessfaces))

for Triangles in bpy.context.active_object.data.tessfaces:
    print("Material: %d Vertices:" % Triangles.material_index, end='')
    for Verts in Triangles.vertices:
        print(" %d" % Verts, end='')
    print()

for Triangles in bpy.context.active_object.data.tessfaces:
    print("M:%d F:" % Triangles.material_index, end='')
    print(str(tuple(Triangles.vertices)))

#############################################################
bpy.context.active_object.name
bpy.context.active_object.data.vertices[0].co
bpy.context.active_object.data.vertices[0].index
bpy.context.active_object.data.vertices[0].normal
bpy.context.active_object.data.vertex_colors.active.data[0].color
bpy.context.active_object.data.uv_layers.active.data[0].uv



print(bpy.context.active_object.data.vertex_colors.active) #None if empty.
print(bpy.context.active_object.data.uv_layers.active) #None if empty.

bpy.context.active_object.children[0].data.vertex_colors.active.data[0].color #Color of the first child.

#detect if coordinates are present.
HasUVCoordinates = bpy.context.active_object.data.uv_layers.active
if HasUVCoordinates is None:
    print("True")




####################################################################
import bpy

def ProcessChildren(ParentMesh, ParentLabel, VerticesInModel, FacesInModel):  #Get all data for sub-meshes.
    VerticesSoFar = VerticesInModel
    FacesSoFar = FacesInModel
    NumberOfChildren = len(ParentMesh.children)
    if NumberOfChildren > 0:
        ChildLabel = ParentLabel + "==>"
        for ChildMesh in ParentMesh.children:
            print(ChildLabel, ChildMesh.name)
            VerticesSoFar = VerticesSoFar + len(ChildMesh.data.vertices)
            ChildMesh.data.update(calc_tessface=True)
            FacesSoFar = FacesSoFar + len(ChildMesh.data.tessfaces)
            VerticesSoFar, FacesSoFar = ProcessChildren(ChildMesh, ChildLabel, VerticesSoFar, FacesSoFar)
    return VerticesSoFar, FacesSoFar

if bpy.context.active_object.type == 'MESH':
    print(bpy.context.active_object.name)
    bpy.context.active_object.data.update(calc_tessface=True)
    VerticesInModel = len(bpy.context.active_object.data.vertices)
    FacesInModel = len(bpy.context.active_object.data.tessfaces)
    VerticesInModel, FacesInModel = ProcessChildren(bpy.context.active_object, "", VerticesInModel, FacesInModel)
    print("Total Vertices:%d" % VerticesInModel)
    print("Total Faces:%d" % FacesInModel)



####################################################################
#There is an assumption that there can only be one material/texture per mesh.
#Make sure the parent object is selected in ObjectMode and not EditMode.
import bpy

def ProcessChildren(ParentMesh, VerticesInModel, FacesInModel):  #Get all data for sub-meshes.
    VerticesSoFar = VerticesInModel
    FacesSoFar = FacesInModel
    NumberOfChildren = len(ParentMesh.children)
    if NumberOfChildren > 0:
        for ChildMesh in ParentMesh.children:
            HasUVCoordinates = ChildMesh.data.uv_layers.active
            HasVertexColors = ChildMesh.data.vertex_colors.active
            CountOfVertices = 0
            print("Name:%s" % ChildMesh.name)
            print("Parent:%s" % ChildMesh.parent.name)
            VerticesSoFar = VerticesSoFar + len(ChildMesh.data.vertices)
            ChildMesh.data.update(calc_tessface=True)
            FacesSoFar = FacesSoFar + len(ChildMesh.data.tessfaces)
            #Vertices.
            for Vertex in ChildMesh.data.vertices:
                print("P:%s" % str(tuple(Vertex.co)))
                if HasUVCoordinates is not None:
                    print(", U:%s" % str(ChildMesh.data.uv_layers.active.data[CountOfVertices].uv))
                else:
                    print(", U:(0.0,0.0)")
                print(", N:%s" % str(tuple(Vertex.normal)))
                if HasVertexColors is not None:
                    print(", C:%s" % str(tuple(ChildMesh.data.vertex_colors.active.data[CountOfVertices].color)))
                else:
                    print(", C:(0.0,0.0,0.0,0.0)")
                print("\n")
                CountOfVertices = CountOfVertices + 1
            #Faces.
            for Face in ChildMesh.data.tessfaces:
                print("F:%s" % str(tuple(Face.vertices)))
                print(" M:%s" % str(Face.material_index))
                print(" S:%s\n" % str(Face.use_smooth))
            #Call child's children.
            VerticesSoFar, FacesSoFar = ProcessChildren(ChildMesh, VerticesSoFar, FacesSoFar)
    return VerticesSoFar, FacesSoFar

if bpy.context.active_object != None and bpy.context.active_object.parent == None and bpy.context.active_object.type == 'MESH':
    print("Punc!It Text\n")
    HasUVCoordinates = bpy.context.active_object.data.uv_layers.active
    HasVertexColors = bpy.context.active_object.data.vertex_colors.active
    NumberOfMaterialsUsed = 0
    CountOfVertices = 0
    #Name.
    print("Name:%s" % bpy.context.active_object.name)
    print("Parent:Root")
    bpy.context.active_object.data.update(calc_tessface=True)
    VerticesInModel = len(bpy.context.active_object.data.vertices)
    FacesInModel = len(bpy.context.active_object.data.tessfaces)
    #Vertices.
    for Vertex in bpy.context.active_object.data.vertices:
        print("P:%s" % str(tuple(Vertex.co)))
        if HasUVCoordinates is not None:
            print(", U:%s" % str(bpy.context.active_object.data.uv_layers.active.data[CountOfVertices].uv))
        else:
            print(", U:(0.0,0.0)")
        print(", N:%s" % str(tuple(Vertex.normal)))
        if HasVertexColors is not None:
            print(", C:%s" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[CountOfVertices].color)))
        else:
            print(", C:(0.0,0.0,0.0,0.0)")
        print("\n")
        CountOfVertices = CountOfVertices + 1
    #Faces.
    for Face in bpy.context.active_object.data.tessfaces:
        print("F:%s" % str(tuple(Face.vertices)))
        print(" M:%s" % str(Face.material_index))
        print(" S:%s\n" % str(Face.use_smooth))
    #Children.
    VerticesInModel, FacesInModel = ProcessChildren(bpy.context.active_object, VerticesInModel, FacesInModel)
    #Materials.
    NumberOfMaterialsUsed = len(bpy.data.materials)
    if NumberOfMaterialsUsed > 0:
        MaterialNumber = 0
        for Material in bpy.data.materials:
            print("M:%d" % MaterialNumber)
            print(" T:%s" % bpy.data.materials[0].texture_slots['MyTexture'].texture.image.name)
            print(" C:%s\n" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[CountOfVertices].color)))
            MaterialNumber = MaterialNumber + 1
    else:
        print("M:None\n");
    print("Total Vertices:%d" % VerticesInModel)
    print("Total Faces:%d" % FacesInModel)
    print("Total Materials:%d" % NumberOfMaterialsUsed)
else:
    print("You must select the root object before running this script!")

####################################################################
import bpy

def ProcessChildren(f, ParentMesh, VerticesInModel, FacesInModel):  #Get all data for sub-meshes.
    VerticesSoFar = VerticesInModel
    FacesSoFar = FacesInModel
    NumberOfChildren = len(ParentMesh.children)
    if NumberOfChildren > 0:
        for ChildMesh in ParentMesh.children:
            HasUVCoordinates = ChildMesh.data.uv_layers.active
            HasVertexColors = ChildMesh.data.vertex_colors.active
            CountOfVertices = 0
            f.write("Name:%s\n" % ChildMesh.name)
            f.write("Parent:%s\n" % ChildMesh.parent.name)
            VerticesSoFar = VerticesSoFar + len(ChildMesh.data.vertices)
            ChildMesh.data.update(calc_tessface=True)
            FacesSoFar = FacesSoFar + len(ChildMesh.data.tessfaces)
            #Materials
            SubMeshMaterialNo = 0
            for Material in ChildMesh.material_slots:
                f.write("M:%d" % SubMeshMaterialNo)
                f.write(" T:%s" % Material.material.texture_slots[0].texture.image.name)
                f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
            #WorldMatrix
            WorldMatrixRowNumber = 0
            for WorldMatrixRow in ChildMesh.matrix_world.row:
                f.write("WMR%d" % WorldMatrixRowNumber)
                f.write(":%s\n" % str(tuple(WorldMatrixRow)))
                WorldMatrixRowNumber = WorldMatrixRowNumber + 1
            #Vertices.
            for Vertex in ChildMesh.data.vertices:
                f.write("P:%s" % str(tuple(Vertex.co)))
                if HasUVCoordinates is not None:
                    f.write(", U:%s" % str(tuple(ChildMesh.data.uv_layers.active.data[CountOfVertices].uv)))
                else:
                    f.write(", U:(0.0,0.0)")
                f.write(", N:%s" % str(tuple(Vertex.normal)))
                if HasVertexColors is not None:
                    f.write(", C:%s" % str(tuple(ChildMesh.data.vertex_colors.active.data[CountOfVertices].color)))
                else:
                    f.write(", C:(0.0,0.0,0.0,0.0)")
                f.write("\n")
                CountOfVertices = CountOfVertices + 1
            #Faces.
            for Face in ChildMesh.data.tessfaces:
                f.write("F:%s" % str(tuple(Face.vertices)))
                f.write(" M:%s" % str(Face.material_index))
                f.write(" S:%s\n" % str(Face.use_smooth)[0])
            #Call child's children.
            VerticesSoFar, FacesSoFar = ProcessChildren(f, ChildMesh, VerticesSoFar, FacesSoFar)
    return VerticesSoFar, FacesSoFar

def write_some_data(context, filepath):
    HasUVCoordinates = bpy.context.active_object.data.uv_layers.active
    HasVertexColors = bpy.context.active_object.data.vertex_colors.active
    print("Exporting data...")
    bpy.context.active_object.data.update(calc_tessface=True)         #calc_tessface=True must be set before working with faces.
    
    f = open(filepath, 'w', encoding='utf-8')
    if bpy.context.active_object != None and bpy.context.active_object.parent == None and bpy.context.active_object.type == 'MESH':
        CountOfVertices = 0
        NumberOfMaterialsUsed = 0
        FacesInModel = 0
        VerticesInModel = len(bpy.context.active_object.data.vertices)
        FacesInModel = len(bpy.context.active_object.data.tessfaces)
        f.write("Punc!It Text\n")
        f.write("Rigid Animation\n")
        f.write("Name:%s\n" % bpy.context.active_object.name)
        f.write("Parent:None\n")
        #Materials
        SubMeshMaterialNo = 0
        for Material in bpy.context.active_object.material_slots:
            f.write("M:%d" % SubMeshMaterialNo)
            f.write(" T:%s" % Material.material.texture_slots[0].texture.image.name)
            f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
        #WorldMatrix
        WorldMatrixRowNumber = 0
        for WorldMatrixRow in bpy.context.active_object.matrix_world.row:
            f.write("WMR%d" % WorldMatrixRowNumber)
            f.write(":%s\n" % str(tuple(WorldMatrixRow)))
            WorldMatrixRowNumber = WorldMatrixRowNumber + 1
        #Vertices.
        for Vertex in bpy.context.active_object.data.vertices:
            f.write("P:%s" % str(tuple(Vertex.co)))
            if HasUVCoordinates is not None:
                f.write(", U:%s" % str(tuple(bpy.context.active_object.data.uv_layers.active.data[CountOfVertices].uv)))
            else:
                f.write(", U:(0.0,0.0)")
            f.write(", N:%s" % str(tuple(Vertex.normal)))
            if HasVertexColors is not None:
                f.write(", C:%s" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[CountOfVertices].color)))
            else:
                f.write(", C:(0.0,0.0,0.0,0.0)")
            f.write("\n")
            CountOfVertices = CountOfVertices + 1
        #Faces.
        for Face in bpy.context.active_object.data.tessfaces:
            f.write("F:%s" % str(tuple(Face.vertices)))
            f.write(" M:%s" % str(Face.material_index))
            f.write(" S:%s\n" % str(Face.use_smooth)[0])  #T if smooth shading & F if flat shading.
        #Children.
        VerticesInModel, FacesInModel = ProcessChildren(f, bpy.context.active_object, VerticesInModel, FacesInModel)
        #Materials.
        #NumberOfMaterialsUsed = len(bpy.data.materials)
        #if NumberOfMaterialsUsed > 0:
        #    MaterialNumber = 0
        #    for Material in bpy.data.materials:
        #        f.write("M:%d" % MaterialNumber)
        #        f.write(" T:%s" % bpy.data.materials[MaterialNumber].texture_slots[0].texture.image.name)
        #        f.write(" C:%s\n" % str(tuple(bpy.data.materials[MaterialNumber].diffuse_color)))
        #        MaterialNumber = MaterialNumber + 1
        #else:
        #    f.write("M:None\n")
        #File Footer.
        f.write("Total Vertices:%d\n" % VerticesInModel)
        f.write("Total Faces:%d\n" % FacesInModel)
        f.write("Total Materials:%d" % NumberOfMaterialsUsed)
    else:
        f.write("You must select the root mesh before exporting the model!")
    f.close()
    
    return {'FINISHED'}


# ExportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator


class ExportSomeData(Operator, ExportHelper):
    """This appears in the tooltip of the operator and in the generated docs"""
    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Export Button"

    # ExportHelper mixin class uses this
    filename_ext = ".txt"

    filter_glob = StringProperty(
            default="*.txt",
            options={'HIDDEN'},
            )

    def execute(self, context):
        return write_some_data(context, self.filepath)


# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
    self.layout.operator(ExportSomeData.bl_idname, text="Custom Exporter Test")


def register():
    bpy.utils.register_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.append(menu_func_export)


def unregister():
    bpy.utils.unregister_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.remove(menu_func_export)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.export_test.some_data('INVOKE_DEFAULT')
=================================================================================

import bpy


def ProcessChildren(f, ParentMesh, VerticesInModel, FacesInModel):  #Get all data for sub-meshes.
    VerticesSoFar = VerticesInModel
    FacesSoFar = FacesInModel
    NumberOfChildren = len(ParentMesh.children)
    if NumberOfChildren > 0:
        for ChildMesh in ParentMesh.children:
            HasUVCoordinates = ChildMesh.data.uv_layers.active
            HasVertexColors = ChildMesh.data.vertex_colors.active
            CountOfVertices = 0
            f.write("Name:%s\n" % ChildMesh.name)
            f.write("Parent:%s\n" % ChildMesh.parent.name)
            VerticesSoFar = VerticesSoFar + len(ChildMesh.data.vertices)
            ChildMesh.data.update(calc_tessface=True)
            FacesSoFar = FacesSoFar + len(ChildMesh.data.tessfaces)
            #Materials
            SubMeshMaterialNo = 0
            for Material in ChildMesh.material_slots:
                f.write("M:%d" % SubMeshMaterialNo)
                f.write("-%s" % Material.name)
                f.write(" T:%s" % Material.material.active_texture.image.name)
                f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
            #WorldMatrix
            WorldMatrixRowNumber = 0
            for WorldMatrixRow in ChildMesh.matrix_world.row:
                f.write("WMR%d" % WorldMatrixRowNumber)
                f.write(":%s\n" % str(tuple(WorldMatrixRow)))
                WorldMatrixRowNumber = WorldMatrixRowNumber + 1
            #Faces.
            FaceCount = 0
            for Face in ChildMesh.data.polygons:
                f.write("F:%d" % FaceCount)
                f.write(" M:%s" % str(Face.material_index))
                f.write(" N:({:f}".format(Face.normal[0]))
                f.write(",{:f}".format(Face.normal[1]))
                f.write(",{:f})".format(Face.normal[2]))
                f.write(" S:%s\n" % str(Face.use_smooth)[0])
                FaceCount = FaceCount + 1
                for Vert, Loop in zip(Face.vertices, Face.loop_indices):
                    f.write("P:%s" % str(tuple(ChildMesh.data.vertices[Vert].co)))
                    if HasUVCoordinates is not None:
                        f.write(", U:%s" % str(tuple(ChildMesh.data.uv_layers.active.data[Loop].uv)))
                    else:
                        f.write(", U:(0.0,0.0)")
                    f.write(", N:%s" % str(tuple(ChildMesh.data.vertices[Vert].normal)))
                    if HasVertexColors is not None:
                        f.write(", C:%s" % str(tuple(ChildMesh.data.vertex_colors.active.data[Vert].color)))
                    else:
                        f.write(", C:(0.0,0.0,0.0,0.0)")
                    f.write("\n")
            #Call child's children.
            VerticesSoFar, FacesSoFar = ProcessChildren(f, ChildMesh, VerticesSoFar, FacesSoFar)
    return VerticesSoFar, FacesSoFar

def write_some_data(context, filepath):
    HasUVCoordinates = bpy.context.active_object.data.uv_layers.active
    HasVertexColors = bpy.context.active_object.data.vertex_colors.active
    print("Exporting data...")
    bpy.context.active_object.data.update(calc_tessface=True)         #calc_tessface=True must be set before working with faces.
    
    f = open(filepath, 'w', encoding='utf-8')
    if bpy.context.active_object != None and bpy.context.active_object.parent == None and bpy.context.active_object.type == 'MESH':
        CountOfVertices = 0
        NumberOfMaterialsUsed = 0
        FacesInModel = 0
        VerticesInModel = len(bpy.context.active_object.data.vertices)
        FacesInModel = len(bpy.context.active_object.data.tessfaces)
        f.write("Punc!It Text\n")
        f.write("Rigid Animation\n")
        f.write("Name:%s\n" % bpy.context.active_object.name)
        f.write("Parent:None\n")
        #Materials
        MaterialNo = 0
        for Material in bpy.context.active_object.material_slots:
            f.write("M:%d" % MaterialNo)
            f.write("-%s" % Material.name)
            f.write(" T:%s" % Material.material.active_texture.image.name)
            f.write(" C:%s\n" % str(tuple(Material.material.diffuse_color)))
        #WorldMatrix
        WorldMatrixRowNumber = 0
        for WorldMatrixRow in bpy.context.active_object.matrix_world.row:
            f.write("WMR%d" % WorldMatrixRowNumber)
            f.write(":%s\n" % str(tuple(WorldMatrixRow)))
            WorldMatrixRowNumber = WorldMatrixRowNumber + 1
        #Faces.
        FaceCount = 0
        for Face in bpy.context.active_object.data.polygons:
            f.write("F:%d" % FaceCount)
            f.write(" M:%s" % str(Face.material_index))
            f.write(" N:({:f}".format(Face.normal[0]))
            f.write(",{:f}".format(Face.normal[1]))
            f.write(",{:f})".format(Face.normal[2]))
            f.write(" S:%s\n" % str(Face.use_smooth)[0])
            FaceCount = FaceCount + 1
            for Vert, Loop in zip(Face.vertices, Face.loop_indices):
                f.write("P:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].co)))
                if HasUVCoordinates is not None:
                    f.write(", U:%s" % str(tuple(bpy.context.active_object.data.uv_layers.active.data[Loop].uv)))
                else:
                    f.write(", U:(0.0,0.0)")
                f.write(", N:%s" % str(tuple(bpy.context.active_object.data.vertices[Vert].normal)))
                if HasVertexColors is not None:
                    f.write(", C:%s" % str(tuple(bpy.context.active_object.data.vertex_colors.active.data[Vert].color)))
                else:
                    f.write(", C:(0.0,0.0,0.0,0.0)")
                f.write("\n")
        #Children.
        VerticesInModel, FacesInModel = ProcessChildren(f, bpy.context.active_object, VerticesInModel, FacesInModel)
        #Footer
        f.write("Total Unique Vertices:%d\n" % VerticesInModel)
        f.write("Total Faces:%d\n" % FacesInModel)
        f.write("Total Materials:%d" % NumberOfMaterialsUsed)
    else:
        f.write("You must select the root mesh before exporting the model!")
    f.close()
    
    return {'FINISHED'}


# ExportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator


class ExportSomeData(Operator, ExportHelper):
    """This appears in the tooltip of the operator and in the generated docs"""
    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Export Button"

    # ExportHelper mixin class uses this
    filename_ext = ".txt"

    filter_glob = StringProperty(
            default="*.txt",
            options={'HIDDEN'},
            )

    def execute(self, context):
        return write_some_data(context, self.filepath)


# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
    self.layout.operator(ExportSomeData.bl_idname, text="Custom Exporter Test")


def register():
    bpy.utils.register_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.append(menu_func_export)


def unregister():
    bpy.utils.unregister_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.remove(menu_func_export)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.export_test.some_data('INVOKE_DEFAULT')
==========================================================================================

bpy.context.active_object.modifiers[0].type
bpy.context.active_object.modifiers[0].object.data.bones[0].name
bpy.context.active_object.modifiers[0].object.data.bones['upper_arm.R'].children[0].name
bpy.context.active_object.modifiers['Armature'].object.data.name
bpy.context.active_object.vertex_groups[0].name

Here is the Blender exporter for exporting skinned animations. Skinned animation takes more than this data. Namely, it takes the "skinning" data. That is, when you skin a model you are assigning vertices to a bone in the armature and when you weight paint, you assign the percentage that each bone influences the vertex. So, all that data has to be exported. I would want to export that data separately; I would export this animation data exactly like this and then export the model as a separate file which would include the skinning data to describe which bones the vertex is influenced by and the percentage weight. I never got around to writing that exporter unfortunately. Learning skinning and weighting in Blender will help understand how to write that exporter and use the data in code.

But this exporter worked to export the armature animation. And having the animation data separate from the model allows the animation data to be re-used on many models. So, a walk animation could be used on any humanoid model that uses the same armature. Since the humanoid armature in Blender is standard, you could reuse the data a lot.

#script to export annimations
import bpy


def write_some_data(context, filepath):
    print("Exporting data...")
    #bpy.context.active_object.data.update(calc_tessface=True)         #calc_tessface=True must be set before working with faces.
    
    f = open(filepath, 'w', encoding='utf-8')
    if bpy.context.active_object != None and bpy.context.active_object.parent == None and bpy.context.active_object.type == 'MESH':
        ModelsArmature = bpy.context.active_object.find_armature()
        f.write("Punc!It Armature Animation\n")
        f.write("Armature Name:%s\n" % ModelsArmature.name)
        for Animation in bpy.data.actions:
            ModelsArmature.animation_data.action = Animation
            f.write("Action:%s\n" % Animation.name)
            
            FirstFrame = bpy.context.scene.frame_start
            LastFrame = bpy.context.scene.frame_end
            f.write("Start:%d\n" % FirstFrame)
            f.write("End:%d\n" % LastFrame)
            bpy.context.scene.frame_set(FirstFrame)
            
            NumberOfKeyFrames = len(Animation.fcurves[0].keyframe_points) #KeyFrames in animation
            for KeyFramePoint in Animation.fcurves[0].keyframe_points:
                KeyFrame = KeyFramePoint.co.x
                bpy.context.scene.frame_set(KeyFrame)                
                f.write("Frame:%d\n" % KeyFrame)
                for Bone in ModelsArmature.pose.bones:
                    f.write("Bone:%s\n" % Bone.name)
                    if (Bone.parent == None):
                        f.write("Parent:None\n")
                    else:
                        f.write("Parent:%s\n" % Bone.parent.name)
                    f.write("Head:%s\n" % str(tuple(Bone.head)))
                    f.write("Tail:%s\n" % str(tuple(Bone.tail)))
                    f.write("Length:%s\n" % str(Bone.length))
                    WorldMatrixRowNumber = 0
                    for WorldMatrixRow in Bone.matrix.row:
                        f.write("WMR:%d" % WorldMatrixRowNumber)
                        f.write(":%s\n" % str(tuple(WorldMatrixRow)))
                        WorldMatrixRowNumber = WorldMatrixRowNumber + 1
                    BasisMatrixRowNumber = 0
                    for BasisMatrixRow in Bone.matrix_basis:
                        f.write("BMR:%d" % BasisMatrixRowNumber)
                        f.write(":%s\n" % str(tuple(BasisMatrixRow)))
                        BasisMatrixRowNumber = BasisMatrixRowNumber + 1
    else:
        f.write("You must select the root mesh before exporting the model!")
    f.close()
    
    return {'FINISHED'}


# ExportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator


class ExportSomeData(Operator, ExportHelper):
    """This appears in the tooltip of the operator and in the generated docs"""
    bl_idname = "export_test.some_data"  # important since its how bpy.ops.import_test.some_data is constructed
    bl_label = "Export Button"

    # ExportHelper mixin class uses this
    filename_ext = ".txt"

    filter_glob = StringProperty(
            default="*.txt",
            options={'HIDDEN'},
            )

    def execute(self, context):
        return write_some_data(context, self.filepath)


# Only needed if you want to add into a dynamic menu
def menu_func_export(self, context):
    self.layout.operator(ExportSomeData.bl_idname, text="Custom Exporter Test")


def register():
    bpy.utils.register_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.append(menu_func_export)


def unregister():
    bpy.utils.unregister_class(ExportSomeData)
    bpy.types.INFO_MT_file_export.remove(menu_func_export)


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.export_test.some_data('INVOKE_DEFAULT')

That should produce a file something like this (This is the short version as the actual data file was too long to post here - you can get the whole thing off my website by downloading the "Armature Animation example" which is an XNA project but contains the Python script and an animation file called "RoboGuyAnimationFile"):


Punc!It Armature Animation
Armature Name:Armature
Action:MyBindPose
Start:1
End:100
Frame:1
Bone:hips
Parent:None
Head:(0.0, 0.0551999993622303, 1.0098999738693237)
Tail:(0.0, 0.017199985682964325, 1.1836999654769897)
Length:0.1779057000841996
WMR:0:(1.0, 0.0, 0.0, 0.0)
WMR:1:(0.0, -0.2135963886976242, -0.9769219756126404, 0.0551999993622303)
WMR:2:(0.0, 0.9769219756126404, -0.2135963886976242, 1.0098999738693237)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:spine
Parent:hips
Head:(0.0, 0.017199985682964325, 1.1836999654769897)
Tail:(0.0, 0.0003999844193458557, 1.3417999744415283)
Length:0.15899010307891734
WMR:0:(1.0, 0.0, 0.0, 0.0)
WMR:1:(0.0, -0.10566695779561996, -0.9944015741348267, 0.017199985682964325)
WMR:2:(0.0, 0.9944015741348267, -0.10566695779561996, 1.1836999654769897)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:ribs
Parent:spine
Head:(0.0, 0.00039998392458073795, 1.3417999744415283)
Tail:(0.0, 0.011400014162063599, 1.6582000255584717)
Length:0.316591208061175
WMR:0:(1.0, 0.0, 0.0, 0.0)
WMR:1:(0.0, 0.034745220094919205, -0.9993961453437805, 0.00039998392458073795)
WMR:2:(0.0, 0.9993961453437805, 0.034745220094919205, 1.3417999744415283)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:neck
Parent:ribs
Head:(0.0, 0.011400015093386173, 1.6582000255584717)
Tail:(0.0, -0.024699967354536057, 1.7812999486923218)
Length:0.1282840587955442
WMR:0:(1.0, 0.0, 0.0, 0.0)
WMR:1:(0.0, -0.28140658140182495, -0.9595885872840881, 0.011400015093386173)
WMR:2:(0.0, 0.9595885872840881, -0.28140658140182495, 1.6582000255584717)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:head
Parent:neck
Head:(0.0, -0.024699965491890907, 1.7812999486923218)
Tail:(0.0, -0.024699928238987923, 1.9347000122070312)
Length:0.153400063514714
WMR:0:(1.0, 0.0, 0.0, 0.0)
WMR:1:(0.0, 2.455568903769745e-07, -0.9999999403953552, -0.024699965491890907)
WMR:2:(0.0, 0.9999999403953552, 2.455568903769745e-07, 1.7812999486923218)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:shoulder.L
Parent:ribs
Head:(0.018300000578165054, -0.06839998811483383, 1.6051000356674194)
Tail:(0.16940002143383026, 0.02050001174211502, 1.6050000190734863)
Length:0.1753123994652116
WMR:0:(0.5070948600769043, 0.8618901968002319, 0.000529240642208606, 0.018300000578165054)
WMR:1:(-0.8618903160095215, 0.5070948004722595, 0.00022575189359486103, -0.06839998811483383)
WMR:2:(-7.374442793661729e-05, -0.0005706493393518031, 0.9999998807907104, 1.6051000356674194)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:upper_arm.L
Parent:shoulder.L
Head:(0.19530001282691956, 0.026700008660554886, 1.5845999717712402)
Tail:(0.30880507826805115, 0.0885000005364418, 1.326655626296997)
Length:0.28850983386843326
WMR:0:(-0.9150146842002869, 0.39341846108436584, 0.08927633613348007, 0.19530001282691956)
WMR:1:(-0.003204085398465395, 0.21420414745807648, -0.9767836928367615, 0.026700008660554886)
WMR:2:(-0.40340808033943176, -0.8940573334693909, -0.19473931193351746, 1.5845999717712402)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(0.7932483553886414, 0.5946226716041565, 0.13107618689537048, 0.0)
BMR:1:(-0.5949065089225769, 0.8027327656745911, -0.04130832478404045, 0.0)
BMR:2:(-0.12978202104568481, -0.045210305601358414, 0.9905112981796265, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:forearm.L
Parent:upper_arm.L
Head:(0.30880507826805115, 0.0885000005364418, 1.326655626296997)
Tail:(0.30192404985427856, 0.049199994653463364, 1.0668660402297974)
Length:0.2628354390933617
WMR:0:(-0.9995909333229065, -0.02618001215159893, 0.011519014835357666, 0.30880507826805115)
WMR:1:(-0.007477705366909504, -0.14952321350574493, -0.9887299537658691, 0.0885000005364418)
WMR:2:(0.027607256546616554, -0.9884114861488342, 0.1492663025856018, 1.326655626296997)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(0.9359229207038879, 0.3483165502548218, -0.05219045653939247, 0.0)
BMR:1:(-0.34817326068878174, 0.9373520016670227, 0.012107320129871368, 0.0)
BMR:2:(0.05313801020383835, 0.006839803420007229, 0.9985637664794922, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:hand.L
Parent:forearm.L
Head:(0.30192404985427856, 0.049199994653463364, 1.0668660402297974)
Tail:(0.2952873706817627, 0.04119998961687088, 0.9873819351196289)
Length:0.0801608916878344
WMR:0:(-0.0008265578071586788, -0.08279184997081757, -0.996566653251648, 0.30192404985427856)
WMR:1:(0.9949796199798584, -0.09979938715696335, 0.007465818431228399, 0.049199994653463364)
WMR:2:(-0.10007485002279282, -0.9915573000907898, 0.08245860785245895, 1.0668660402297974)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.01.L
Parent:hand.L
Head:(0.3039860129356384, 0.022399989888072014, 1.0296443700790405)
Tail:(0.2986827790737152, 0.0050999801605939865, 0.9624106884002686)
Length:0.0696260194040096
WMR:0:(-0.00568762794137001, -0.0761675164103508, -0.9970789551734924, 0.3039860129356384)
WMR:1:(0.9685460329055786, -0.24847060441970825, 0.013455983251333237, 0.022399989888072014)
WMR:2:(-0.24876970052719116, -0.9656403064727783, 0.07518486678600311, 1.0296443700790405)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.01.L
Parent:palm.01.L
Head:(0.2986827790737152, 0.0050999801605939865, 0.9624106884002686)
Tail:(0.2806694805622101, 0.001299968920648098, 0.9213048815727234)
Length:0.045040052882204376
WMR:0:(0.0950925275683403, -0.3999395966529846, -0.9115952253341675, 0.2986827790737152)
WMR:1:(0.9865608215332031, -0.08436965197324753, 0.13992759585380554, 0.0050999801605939865)
WMR:2:(-0.1328735500574112, -0.9126502871513367, 0.3865416646003723, 0.9624106884002686)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.02.L
Parent:finger_index.01.L
Head:(0.2806694805622101, 0.0012999688042327762, 0.9213048815727234)
Tail:(0.2655388414859772, -0.00030004081781953573, 0.8975337743759155)
Length:0.028223426563902844
WMR:0:(0.08646058291196823, -0.5361015200614929, -0.8397141695022583, 0.2806694805622101)
WMR:1:(0.9888078570365906, -0.056690819561481476, 0.13800522685050964, 0.0012999688042327762)
WMR:2:(-0.12158889323472977, -0.8422480225563049, 0.5251997709274292, 0.9213048815727234)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.03.L
Parent:finger_index.02.L
Head:(0.2655388414859772, -0.00030004081781953573, 0.8975337743759155)
Tail:(0.24943029880523682, 0.0005999515415169299, 0.881397008895874)
Length:0.02281864004935344
WMR:0:(0.11580153554677963, -0.7059381008148193, -0.6987428069114685, 0.2655388414859772)
WMR:1:(0.9914401769638062, 0.03944113105535507, 0.1244625449180603, -0.00030004081781953573)
WMR:2:(-0.06030363589525223, -0.7071748375892639, 0.7044626474380493, 0.8975337743759155)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.01.L
Parent:palm.01.L
Head:(0.28035271167755127, 0.021399999037384987, 1.0403861999511719)
Tail:(0.2600117325782776, 0.0014999918639659882, 1.0098435878753662)
Length:0.04174466275624186
WMR:0:(0.8725852370262146, -0.48727157711982727, -0.034081779420375824, 0.28035271167755127)
WMR:1:(-0.23309919238090515, -0.47670814394950867, 0.8475931882858276, 0.021399999037384987)
WMR:2:(-0.42925503849983215, -0.7316528558731079, -0.5295511484146118, 1.0403861999511719)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.02.L
Parent:thumb.01.L
Head:(0.2600117325782776, 0.0014999917475506663, 1.0098435878753662)
Tail:(0.24852174520492554, -0.00570001220330596, 0.9792690873146057)
Length:0.03344637428703545
WMR:0:(0.9349398016929626, -0.3435346186161041, 0.08872213214635849, 0.2600117325782776)
WMR:1:(-0.1703493595123291, -0.21526996791362762, 0.9615820050239563, 0.0014999917475506663)
WMR:2:(-0.3112374246120453, -0.9141350984573364, -0.2597854435443878, 1.0098435878753662)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.03.L
Parent:thumb.02.L
Head:(0.24852174520492554, -0.00570001220330596, 0.9792690873146057)
Tail:(0.24306833744049072, -0.009800013154745102, 0.9596298933029175)
Length:0.02079056529957112
WMR:0:(0.9595236778259277, -0.2623019218444824, 0.10252860188484192, 0.24852174520492554)
WMR:1:(-0.1573072373867035, -0.19720466434955597, 0.9676594138145447, -0.00570001220330596)
WMR:2:(-0.2335997223854065, -0.944620668888092, -0.23048460483551025, 0.9792690873146057)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.02.L
Parent:hand.L
Head:(0.3061484098434448, 0.038899991661310196, 1.0252189636230469)
Tail:(0.3019583523273468, 0.02769998088479042, 0.9580886363983154)
Length:0.06818707837033267
WMR:0:(-0.014553106389939785, -0.06144958361983299, -0.9980041980743408, 0.3061484098434448)
WMR:1:(0.9864088296890259, -0.1642541140317917, -0.004270466044545174, 0.038899991661310196)
WMR:2:(-0.1636638641357422, -0.9845023155212402, 0.06300473213195801, 1.0252189636230469)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.01.L
Parent:palm.02.L
Head:(0.3019583523273468, 0.02769998274743557, 0.9580886363983154)
Tail:(0.2784064710140228, 0.023399967700242996, 0.9147172570228577)
Length:0.049540466204234135
WMR:0:(0.03002334013581276, -0.4754068851470947, -0.8792536854743958, 0.3019583523273468)
WMR:1:(0.9929408431053162, -0.08679802715778351, 0.08083651959896088, 0.02769998274743557)
WMR:2:(-0.11474771052598953, -0.8754739761352539, 0.4694449007511139, 0.9580886363983154)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.02.L
Parent:finger_middle.01.L
Head:(0.2784064710140228, 0.023399967700242996, 0.9147172570228577)
Tail:(0.256862610578537, 0.021799959242343903, 0.8908450603485107)
Length:0.032195958187134936
WMR:0:(-0.016263922676444054, -0.6691475510597229, -0.7429516315460205, 0.2784064710140228)
WMR:1:(0.9985017776489258, -0.049695923924446106, 0.022901061922311783, 0.023399967700242996)
WMR:2:(-0.052245840430259705, -0.741466224193573, 0.6689532399177551, 0.9147172570228577)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.03.L
Parent:finger_middle.02.L
Head:(0.256862610578537, 0.021799959242343903, 0.8908450603485107)
Tail:(0.23979225754737854, 0.02159995399415493, 0.8758766055107117)
Length:0.022704439982939768
WMR:0:(-0.01572253555059433, -0.7518513798713684, -0.659145176410675, 0.256862610578537)
WMR:1:(0.9998658895492554, -0.008809125982224941, -0.01380158681422472, 0.021799959242343903)
WMR:2:(0.004570264369249344, -0.6592739820480347, 0.7518890500068665, 0.8908450603485107)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.03.L
Parent:hand.L
Head:(0.3055240213871002, 0.05449999123811722, 1.0256550312042236)
Tail:(0.30269524455070496, 0.05209998041391373, 0.955956220626831)
Length:0.06979746575807515
WMR:0:(-0.040807563811540604, -0.040528569370508194, -0.9983448386192322, 0.3055240213871002)
WMR:1:(0.9986307621002197, -0.034385357052087784, -0.03942333161830902, 0.05449999123811722)
WMR:2:(-0.03273067623376846, -0.9985866546630859, 0.0418761782348156, 1.0256550312042236)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_ring.01.L
Parent:palm.03.L
Head:(0.30269524455070496, 0.05209998041391373, 0.955956220626831)
Tail:(0.27694419026374817, 0.04989996924996376, 0.9193423390388489)
Length:0.044816661755981785
WMR:0:(-0.05744895339012146, -0.5745863914489746, -0.8164253234863281, 0.30269524455070496)
WMR:1:(0.9981566071510315, -0.049089159816503525, -0.03568858653306961, 0.05209998041391373)
WMR:2:(-0.019571460783481598, -0.8169706463813782, 0.5763472318649292, 0.955956220626831)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_ring.02.L
Parent:finger_ring.01.L
Head:(0.27694419026374817, 0.04989996924996376, 0.9193423390388489)
Tail:(0.25495731830596924, 0.0493999607861042, 0.8963721990585327)
Length:0.03180094145881558
WMR:0:(-0.06333208084106445, -0.691390335559845, -0.7197003960609436, 0.27694419026374817)
WMR:1:(0.997233510017395, -0.01572306454181671, -0.07264977693557739, 0.04989996924996376)
WMR:2:(0.038913462311029434, -0.7223105430603027, 0.6904733180999756, 0.9193423390388489)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_ring.03.L
Parent:finger_ring.02.L
Head:(0.25495731830596924, 0.0493999607861042, 0.8963721990585327)
Tail:(0.2385593205690384, 0.049799952656030655, 0.8877090811729431)
Length:0.01855003867316774
WMR:0:(-0.054464541375637054, -0.8839878439903259, -0.46432676911354065, 0.25495731830596924)
WMR:1:(0.9873839020729065, 0.021562909707427025, -0.156869575381279, 0.0493999607861042)
WMR:2:(0.14868304133415222, -0.4670126736164093, 0.8716609477996826, 0.8963721990585327)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.04.L
Parent:hand.L
Head:(0.3034741282463074, 0.06959999352693558, 1.0283842086791992)
Tail:(0.29747551679611206, 0.0762999877333641, 0.9541244506835938)
Length:0.07480230557451074
WMR:0:(-0.003450550138950348, -0.08019282668828964, -0.9967735409736633, 0.3034741282463074)
WMR:1:(0.9959237575531006, 0.08956936001777649, -0.010653658770024776, 0.06959999352693558)
WMR:2:(0.09013469517230988, -0.9927470684051514, 0.07955678552389145, 1.0283842086791992)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_pinky.01.L
Parent:palm.04.L
Head:(0.29747551679611206, 0.0762999877333641, 0.9541244506835938)
Tail:(0.27759575843811035, 0.07649997621774673, 0.9345836043357849)
Length:0.027876324430510892
WMR:0:(-0.12287505716085434, -0.7131419777870178, -0.6901670098304749, 0.29747551679611206)
WMR:1:(0.9831879138946533, 0.007174238096922636, -0.18245655298233032, 0.0762999877333641)
WMR:2:(0.13506880402565002, -0.7009831666946411, 0.7002708315849304, 0.9541244506835938)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_pinky.02.L
Parent:finger_pinky.01.L
Head:(0.27759575843811035, 0.07649997621774673, 0.9345836043357849)
Tail:(0.2601030468940735, 0.0769999697804451, 0.9202945828437805)
Length:0.022592500656735275
WMR:0:(-0.11284443736076355, -0.7742713093757629, -0.6227120757102966, 0.27759575843811035)
WMR:1:(0.9785446524620056, 0.022131117060780525, -0.2048439085483551, 0.07649997621774673)
WMR:2:(0.172386035323143, -0.6324669718742371, 0.755161464214325, 0.9345836043357849)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_pinky.03.L
Parent:finger_pinky.02.L
Head:(0.2601030468940735, 0.0769999697804451, 0.9202945828437805)
Tail:(0.24699437618255615, 0.07719997316598892, 0.9129698276519775)
Length:0.015017632562992945
WMR:0:(-0.10453005135059357, -0.8728853464126587, -0.4765971899032593, 0.2601030468940735)
WMR:1:(0.9713146686553955, 0.013317709788680077, -0.23742561042308807, 0.0769999697804451)
WMR:2:(0.21359246969223022, -0.48774388432502747, 0.8464540839195251, 0.9202945828437805)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:shoulder.R
Parent:ribs
Head:(-0.018300000578165054, -0.06839998811483383, 1.6051000356674194)
Tail:(-0.16940002143383026, 0.02050001174211502, 1.6050000190734863)
Length:0.1753123994652116
WMR:0:(0.5070948600769043, -0.8618901968002319, -0.000529240642208606, -0.018300000578165054)
WMR:1:(0.8618903160095215, 0.5070948004722595, 0.00022575189359486103, -0.06839998811483383)
WMR:2:(7.374442793661729e-05, -0.0005706493393518031, 0.9999998807907104, 1.6051000356674194)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:upper_arm.R
Parent:shoulder.R
Head:(-0.19530001282691956, 0.026700008660554886, 1.5845999717712402)
Tail:(-0.3024795651435852, 0.0885000005364418, 1.3239638805389404)
Length:0.28850973550906783
WMR:0:(-0.924582302570343, -0.3714936375617981, -0.08449970185756683, -0.19530001282691956)
WMR:1:(0.0032040609512478113, 0.21420414745807648, -0.9767836928367615, 0.026700008660554886)
WMR:2:(0.3809690773487091, -0.9033876061439514, -0.19685900211334229, 1.5845999717712402)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(0.7781602144241333, -0.6133349537849426, -0.1352292150259018, 0.0)
BMR:1:(0.6136394739151001, 0.7883368134498596, -0.04440385103225708, 0.0)
BMR:2:(0.13384060561656952, -0.04842866212129593, 0.9898188710212708, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:forearm.R
Parent:upper_arm.R
Head:(-0.3024795651435852, 0.0885000005364418, 1.3239637613296509)
Tail:(-0.30127403140068054, 0.049199994653463364, 1.064085841178894)
Length:0.26283545642833384
WMR:0:(-0.9999554753303528, 0.004586691502481699, -0.008256259374320507, -0.3024795651435852)
WMR:1:(0.007477679755538702, -0.14952321350574493, -0.9887299537658691, 0.0885000005364418)
WMR:2:(-0.005769494455307722, -0.9887475967407227, 0.14948229491710663, 1.3239637613296509)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(0.9512011408805847, -0.3051568865776062, 0.04577907174825668, 0.0)
BMR:1:(0.30504775047302246, 0.9522894620895386, 0.009522203356027603, 0.0)
BMR:2:(-0.04650069400668144, 0.004907271824777126, 0.9989061951637268, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:hand.R
Parent:forearm.R
Head:(-0.30127403140068054, 0.049199994653463364, 1.064085841178894)
Tail:(-0.2963748872280121, 0.04119998961687088, 0.9844757318496704)
Length:0.08016090818859924
WMR:0:(0.0013592976611107588, 0.06111632287502289, 0.9981299042701721, -0.30127403140068054)
WMR:1:(-0.9949796199798584, -0.09979937970638275, 0.007465844042599201, 0.049199994653463364)
WMR:2:(0.10006904602050781, -0.9931290149688721, 0.06067381799221039, 1.064085841178894)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.01.R
Parent:hand.R
Head:(-0.30414843559265137, 0.022399989888072014, 1.0269181728363037)
Tail:(-0.30031484365463257, 0.005099982023239136, 0.9595847129821777)
Length:0.0696260117714473
WMR:0:(-0.00025309206102974713, 0.05505960434675217, 0.9984832406044006, -0.30414843559265137)
WMR:1:(-0.9685460329055786, -0.24847058951854706, 0.013456009328365326, 0.022399989888072014)
WMR:2:(0.24883460998535156, -0.9670735001564026, 0.05339062586426735, 1.0269181728363037)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.01.R
Parent:palm.01.R
Head:(-0.30031484365463257, 0.005099981091916561, 0.9595847129821777)
Tail:(-0.2832036018371582, 0.0011999702546745539, 0.9180952906608582)
Length:0.04504860536824087
WMR:0:(0.09713990241289139, 0.379839688539505, 0.9199380874633789, -0.30031484365463257)
WMR:1:(-0.9863735437393188, -0.08657345920801163, 0.1399010419845581, 0.005099981091916561)
WMR:2:(0.1327822059392929, -0.9209924936294556, 0.366254061460495, 0.9595847129821777)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.02.R
Parent:finger_index.01.R
Head:(-0.2832036018371582, 0.0011999703710898757, 0.9180952906608582)
Tail:(-0.26859575510025024, -0.000300038605928421, 0.8939993977546692)
Length:0.028217924589995197
WMR:0:(0.0909094512462616, 0.5176796913146973, 0.8507311940193176, -0.2832036018371582)
WMR:1:(-0.989000141620636, -0.0531579852104187, 0.1380321979522705, 0.0011999703710898757)
WMR:2:(0.11667963862419128, -0.8539217114448547, 0.5071527361869812, 0.9180952906608582)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_index.03.R
Parent:finger_index.02.R
Head:(-0.26859575510025024, -0.0003000386350322515, 0.8939993977546692)
Tail:(-0.2528434991836548, 0.0005999548593536019, 0.877514660358429)
Length:0.022818635404477372
WMR:0:(0.11709101498126984, 0.6903250813484192, 0.713961660861969, -0.26859575510025024)
WMR:1:(-0.9914400577545166, 0.03944117948412895, 0.1244625598192215, -0.0003000386350322515)
WMR:2:(0.05776016414165497, -0.7224237322807312, 0.689034104347229, 0.8939993977546692)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.01.R
Parent:palm.01.R
Head:(-0.28028616309165955, 0.021399999037384987, 1.0371413230895996)
Tail:(-0.26061710715293884, 0.0014999937266111374, 1.0061618089675903)
Length:0.04174460765326611
WMR:0:(0.8817521929740906, 0.4711759388446808, 0.022508161142468452, -0.28028616309165955)
WMR:1:(0.23309920728206635, -0.4767081141471863, 0.8475931882858276, 0.021399999037384987)
WMR:2:(0.41009530425071716, -0.7421203851699829, -0.5301691889762878, 1.0371413230895996)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.02.R
Parent:thumb.01.R
Head:(-0.26061710715293884, 0.0014999930281192064, 1.0061618089675903)
Tail:(-0.24979761242866516, -0.005700009874999523, 0.975343644618988)
Length:0.03344638632734788
WMR:0:(0.9415143728256226, 0.3234878182411194, -0.09437473118305206, -0.26061710715293884)
WMR:1:(0.1703493744134903, -0.21526993811130524, 0.9615820050239563, 0.0014999930281192064)
WMR:2:(0.29074400663375854, -0.9214198589324951, -0.25778576731681824, 1.0061618089675903)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:thumb.03.R
Parent:thumb.02.R
Head:(-0.24979761242866516, -0.0057000103406608105, 0.975343644618988)
Tail:(-0.24477443099021912, -0.009800011292099953, 0.955590009689331)
Length:0.020790585669949638
WMR:0:(0.9643967747688293, 0.241608664393425, -0.10753796994686127, -0.24979761242866516)
WMR:1:(0.15730726718902588, -0.19720463454723358, 0.9676594138145447, -0.0057000103406608105)
WMR:2:(0.21258790791034698, -0.9501240253448486, -0.2281903773546219, 0.975343644618988)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.02.R
Parent:hand.R
Head:(-0.3064069449901581, 0.038899991661310196, 1.0225409269332886)
Tail:(-0.3036840260028839, 0.02769998274743557, 0.9553350806236267)
Length:0.06818709750150699
WMR:0:(-0.010975182056427002, 0.0399332270026207, 0.9991422295570374, -0.3064069449901581)
WMR:1:(-0.9864088296890259, -0.1642540991306305, -0.004270440433174372, 0.038899991661310196)
WMR:2:(0.16394269466400146, -0.9856095910072327, 0.04119318351149559, 1.0225409269332886)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.01.R
Parent:palm.02.R
Head:(-0.3036840260028839, 0.02769998274743557, 0.9553350806236267)
Tail:(-0.2810850143432617, 0.023299969732761383, 0.9114596843719482)
Length:0.04954922641941893
WMR:0:(0.03160826116800308, 0.4560922086238861, 0.8893712162971497, -0.3036840260028839)
WMR:1:(-0.992764949798584, -0.08880080282688141, 0.08082223683595657, 0.02769998274743557)
WMR:2:(0.11583929508924484, -0.8854911923408508, 0.44998544454574585, 0.9553350806236267)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.02.R
Parent:finger_middle.01.R
Head:(-0.2810850143432617, 0.023299969732761383, 0.9114596843719482)
Tail:(-0.2600676715373993, 0.0217999629676342, 0.887122631072998)
Length:0.032191161553918914
WMR:0:(-0.01309398002922535, 0.6528918147087097, 0.757338285446167, -0.2810850143432617)
WMR:1:(-0.9986511468887329, -0.046596869826316833, 0.022904489189386368, 0.023299969732761383)
WMR:2:(0.050243765115737915, -0.7560167908668518, 0.6526212692260742, 0.9114596843719482)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_middle.03.R
Parent:finger_middle.02.R
Head:(-0.2600676715373993, 0.0217999629676342, 0.887122631072998)
Tail:(-0.2433283030986786, 0.02159995771944523, 0.8717849254608154)
Length:0.02270444166396787
WMR:0:(-0.01581859029829502, 0.7372732758522034, 0.6754097938537598, -0.2600676715373993)
WMR:1:(-0.9998659491539001, -0.008809060789644718, -0.013801590539515018, 0.0217999629676342)
WMR:2:(-0.004225800279527903, -0.6755375266075134, 0.7373137474060059, 0.887122631072998)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:palm.03.R
Parent:hand.R
Head:(-0.30577319860458374, 0.054399993270635605, 1.022963285446167)
Tail:(-0.3044673204421997, 0.05209998041391373, 0.9532193541526794)
Length:0.06979406371022387
WMR:0:(-0.04005623981356621, 0.01871049590408802, 0.9990224242210388, -0.30577319860458374)
WMR:1:(-0.9986790418624878, -0.032954249531030655, -0.039425238966941833, 0.054399993270635605)
WMR:2:(0.03218439221382141, -0.9992818832397461, 0.020005786791443825, 1.022963285446167)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_ring.01.R
Parent:palm.03.R
Head:(-0.3044673204421997, 0.05209998041391373, 0.9532193541526794)
Tail:(-0.2795220613479614, 0.04989997297525406, 0.9160518050193787)
Length:0.044816656419072176
WMR:0:(-0.057007744908332825, 0.5566065907478333, 0.8288182616233826, -0.3044673204421997)
WMR:1:(-0.9981566667556763, -0.04908903315663338, -0.035688575357198715, 0.05209998041391373)
WMR:2:(0.020821411162614822, -0.8293249011039734, 0.5583789348602295, 0.9532193541526794)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
Bone:finger_ring.02.R
Parent:finger_ring.01.R
Head:(-0.2795220613479614, 0.04989997297525406, 0.9160518050193787)
Tail:(-0.2580421268939972, 0.0493999682366848, 0.8926069140434265)
Length:0.03180095127129806
WMR:0:(-0.06416677683591843, 0.6754500865936279, 0.7346089482307434, -0.2795220613479614)
WMR:1:(-0.9972335696220398, -0.015722934156656265, -0.0726497694849968, 0.04989997297525406)
WMR:2:(-0.037521060556173325, -0.7372384071350098, 0.6745902895927429, 0.9160518050193787)
WMR:3:(0.0, 0.0, 0.0, 1.0)
BMR:0:(1.0, 0.0, 0.0, 0.0)
BMR:1:(0.0, 1.0, 0.0, 0.0)
BMR:2:(0.0, 0.0, 1.0, 0.0)
BMR:3:(0.0, 0.0, 0.0, 1.0)
...

This topic is closed to new replies.

Advertisement