Jump to content
  • entries
    12
  • comments
    636
  • views
    10,833

The Effin Export/Import Project


Bad Dog

8,992 views

Edit: For the record, this tool is implemented and has its own thread here: 

 

I can't really do what I want to do with FO4 if I can't do proper weight painting and I don't have full control over the nifs I create. So I've decided to have a look at making proper import/export tools between Blender and FO4. I'm using this blog to track thoughts and progress notes along the way.

 

There are two possible routes:

  1. Extend the niftools package. That is currently being actively worked on, tho there was a long hiatus for the past few years, which meant I was stuck with old versions of Blender and a multi-step conversion process. The recent versions support the latest Blender and maybe have better export--I haven't yet seen a version which exports properly but I haven't tested the latest. Upside of this method is it ties into an existing project and extends the tools that have been around forever. Downside is this stack is very complicated--translation generated from XML files, read/write through pyffi, and so forth. I'm told the XML for FO4 has been written but pyffi needs updating to use it. Presumably higher levels of the stack would need work too? Dunno. 
  2. Bodyslide/OS has export/import to all games and they stay up to date all the time. Their nif code is cleanly separated into a package called Nifly, which is used by BS/OS, Cathedral tools, and Nif Optimizer. So it seems like robust code with an active community behind it. Downside is I'd have to access it from a Blender python addon, and I have to figure out how to walk the Blender representation of a model so as to push it at Nifly.

 

I've looked a little bit at both options. My feeling right now is that the hard part of the niftools route is digging into XML, generated code, and pyffi. The hard part of the Nifly route is figuring out how to bolt it into Blender and parse the Blender data model. That seems more straightforward. It's all known stuff--Blender addons and such. So until I hit a roadblock, I'm going to explore that.

 

The biggest issue is whether I can call the C++ Nifly code from a Blender addon. I hunted through other addons and found an import/export addon that does exactly that. So in theory I just copy their method.

 

So here's the project:

  1. Figure out how to make a Blender export/import addon
  2. Figure out how to make a DLL
  3. Make a dummy DLL and call it from a dummy export/import addon. Once that's done I know I can get data into and out of Blender.
  4. Make a DLL encapsulating Nifly
  5. Call that DLL from my Blender addon. 
  6. Keep adding features until done.

 

#1 is mostly done--I have a little script that pretends to be an export/import addon but does nothing. On to #2.

Edited by Bad Dog

175 Comments


Recommended Comments



I am legit going to die. There is no part of this technology mix I'm fluent with except maybe python. 

 

That said, I have steps 1-3 above done; I can invoke a C++ DLL from a Blender addon. I can compile OS's nifly code. I'm now working on how to push data across the DLL interface, which does not seem to be as simple as a regular call. But progress is being made.

 

Next step: actually use nifly to open a file and pull something like the version string out of it. Then I'll do the same from the python addon and we'll be cooking with gas.

Link to comment

I can now "import" a nif file into blender and read the shapes it contains:

 

image.png

 

Observe that nifly does not care if it's a FO4 nif or a Skyrim nif.

 

Now the real work can start.

Link to comment
1 hour ago, Bad Dog said:

Now the real work can start.

Can't wait to see where this goes. Not well versed in Blender-fu myself so it won't be uber-useful for me (it will still be useful nevertheless, tho), but having working nif Import/Export (which not even Max has) on free software will probably really come in handy for the modding community as a whole. :classic_rolleyes:

Link to comment

Golly, animations. I know literally nothing about them and I don't know how much help the OS code will be. But hey, if I have someone who cares and can tell me how it's supposed to work I can give it a try, once the rest of it's in place.

 

I've been thinking about all the things I can do once I have this in place. Like

- export tris and nifs at the same time

- split seams as required for nifs during the exports so that tris always match their nifs and I never have to worry about bone weights matching across a seam

- generate _0 and _1 nifs from shape keys automatically. Same for FO4 facebone meshes

 

squeeee

Link to comment
49 minutes ago, Bad Dog said:

- export tris and nifs at the same time

- split seams as required for nifs during the exports so that tris always match their nifs and I never have to worry about bone weights matching across a seam

- generate _0 and _1 nifs from shape keys automatically. Same for FO4 facebone meshes

 

tenor.gif?itemid=11159759

Link to comment
1 hour ago, Bad Dog said:

Golly, animations. I know literally nothing about them and I don't know how much help the OS code will be. But hey, if I have someone who cares and can tell me how it's supposed to work I can give it a try, once the rest of it's in place.

 

Well, the thing that's been holding me up is that I can't get the skeleton into Blender to animate. I mean, I can, but it doesn't import right and the model is deformed. So if you can make it so I can import a body mesh with bones and rigging from a skeleton.nif, that would be golden :)

 

And from what you were saying at the start about weight painting, I'm guessing that's not a million miles from some of the uses you have in mind.

 

I better leave it there - I have to dash.

Link to comment

Yep, that I'll have to do. Import the armor with bones, bones are rigged to the mesh in blender. If you have nifs that tend to be a problem I'll make sure they work.

Link to comment

Are you planning on making a repo for this in the future? I'm sure some of us would contribute.

Link to comment

Yeah. Not yet because I have no idea what the fuck I'm doing, but as soon as things settle down a bit and I have a basic framework.

 

I figure stage 1 is: export/import of mesh, UV, and bone weights. Shaders don't matter, we've all been copying them from other nifs since forever. Other nif contents don't matter, we've been copying those around since forever too. The nifly code makes it easy to just ignore the parts of a nif we can't deal with. Partitions do matter and they're probably the first next thing to work on, but OS handles those pretty well. You don't have to be as precise as with weights. 

 

Gimme a week or two. This is going fast.

Link to comment

And I can now import UVs:

 

image.png

 

Next up is either bones or getting started on export. Export will be a whole new thing. Maybe bones.

Link to comment

I'm loading up armatures but there's something skeezy with bone rotations that I haven't figured out yet. I think I'll do weight groups first so I can see how the bones affect the mesh.

 

I'm thinking, is there any reason not to connect up the armature when importing? Then it would be ready for posing from the git-go. I'd have to know the skeletons for the different games, but heck there's really only two.

 

Link to comment
7 hours ago, Bad Dog said:

I'm loading up armatures but there's something skeezy with bone rotations that I haven't figured out yet.

 

Yeah. That seems to be the problem the Blender niftools importer hit. It'll import the skeleton, but all the bones are all pointing the same way.

 

7 hours ago, Bad Dog said:

I'm thinking, is there any reason not to connect up the armature when importing? Then it would be ready for posing from the git-go. I'd have to know the skeletons for the different games, but heck there's really only two.

 

 

When I was animating for Skyrim, I imported the skeleton nif, then imported the body mesh expecting to have to do some basic weighting so I could get an idea what it would look like. I was pleasantly surprised to find that once I parented the armature, the weighting was already there. So that's possibly the most flexible approach if you can swing it.

 

That said, I'm horribly new to this whole animation thing, and barely competent with nifscope, so I may be talking complete and utter cobblers. Just saying.

 

Link to comment

Heh. I *think* that the visual orientation of the bone has very little to do with anything. I think the orientation data is part of the bone and the head location is the location of the bone, but the location of the tail is whatever's convenient. Then there's bone roll, which sounds like it should rotate about the axis of the bone, but I don't know why it has to be extra. 

 

Since the niftools importer isn't making guesses about bone relationships beyond what's in the file, what they do is convenient for grabbing the bones when you're looking at the model from the front. There's an option to glue the head of the bone to the tail of the parent though, which another importer uses, and I could use that to give you a connected skeleton. 

 

Bone weights are easy--they're just vertex groups that happen to be named the same as a bone in the parent skeleton, if there is one.

 

Edit: Also I can't figure out the skin transform with FO4 heads. Blaze upthread describes how they are modeled at the origin and then use a skin transform to lift them up into the right position, and I can see that in nifskope. But I can't find the place in the file where the transform is defined. Other meshes, like the Skyrim heads, have a transform right on the mesh, and that makes sense to me. But FO4 is doing something different.

Link to comment
6 hours ago, Bad Dog said:

Other meshes, like the Skyrim heads, have a transform right on the mesh, and that makes sense to me. But FO4 is doing something different.

It's the skinning itself. If you remove skinning, they snap back to origin. No idea how that works but you can see that in effect if you load an skinned facegen mesh into OS and go edit -> remove skinning.

Link to comment

Yeah, but pretty soon I'm going to have to really really know how it works. Probably. Nifly has a bunch of functions like "getskinbonetransformtogloballocalshape" and maybe if I call the right one it will do the right thing without my having to understand it.

 

Meanwhile, I'm now importing the armature and parenting the mesh to it with bone weights:

 

image.png

 

image.png

 

I'm pretty sure there's a million special cases having to do with the aforementioned transforms that I'm not handling correctly but for now this is good. Next step, export.

Link to comment

I am now exporting nifs from Blender:

 

image.png

 

I'm not doing weights and armatures yet but that's a cube with quads and a UV that requires the mesh to be split so every vert has a unique UV location, and export does all that on its own without asking the user to do it and WITHOUT MUCKING UP YOUR ORIGINAL MESH.

 

And I am AWESOME and EVERYBODY SHOULD LOVE ME.

 

Link to comment

You are indeed awesome.

 

Any thoughts on a timeframe for a possible release? I'm keen to have a play with this gizmo :)

Link to comment

Maybe another week? I want to have export/import of partitions and export/import of bone weights and armatures working first. And I need to do a bunch of testing to make sure the models actually work in the different games. Also I need to integrate it with Blender properly, so you can install it and you can choose your game through Blender's UI. Then I'll put up a github and a kit people can play with.

 

Then, in something like this order:

  1. Integrate the tri export/import code. On export, export all tris recognized for the target game automatically. For the chargen file either do the same, or export all shapes that end in brackets, so modders can add their own. I don't think there's any utility to adding morphs to the expression tri file, but tools like RaceMenu can make use of additional morphs in the chargen file.
  2. On import, merge imported tris into the active object. Create a new shape if there is none, or if the tris don't match. 
  3. Export/import of alternate body weights. I'm thinking any shape key that starts with a "_" automatically produces a file with the name <basename>_<shapekey>.nif. That way you can create _0 and _1 shapes and get boht files automatically.
  4. Recognize the bones of the armature and rename them to follow blender conventions, as the niftools importer does. Hook the bones up into a connected skeleton on import.
  5. Deal with shaders. On import, create shader nodes in blender to reflect what the nif is doing. On export, use properly-set-up nodes to generate a working shader.

Once step 1 is done I'll also be working on Furry Fallout so development will slow down.

Link to comment
1 hour ago, Bad Dog said:

Integrate the tri export/import code

 

Ooh! Would that let me import facial expressions for models? That would take a lot of the guesswork out of ball gags and the like.

Link to comment

"OMG I have to be able to import tris to make sure my ball gags fit" is not the first use case I had in mind for this stuff. ?

 

Export is working with weights, maybe--still have to tie it all the way back to blender. Got tests working through blender so I can test the whole chain from blender object to nif. Then spent a bunch of time importing and exporting different nifs just because. Might do more work tomorrow.

Link to comment
4 hours ago, Bad Dog said:

"OMG I have to be able to import tris to make sure my ball gags fit" is not the first use case I had in mind for this stuff.

 

No, but if you're doing it anyway, I can think of ways I'd like to use it :D

 

You're making great progress here! I'm really looking forward to having a play with all this.

Link to comment

Spent a bunch of the weekend working on this and I'm kinda drug out. Made good progress but not a lot of visible progress and spent a lot of time digging dry wells.

 

I was ready to export weights and bones but Ousnius pointed out I was gonna need normals so I got those in. Then I had to spend a bunch of time cruising the OS/nifly code to see how weights were set up, which is complicated because FO and Skyrim do it completely differently. Eventually got a test program working that writes what appears to be correct bones and weights, but the setup is a huge hassle--have to define verts, faces, weights, uvs, everything in c++ arrays. 

 

So I decided I wasn't happy with my test setup, which was working entirely outside blender. Found a little script magic which would let me run the tests in blender, and got them moved over. That's good because I can write a test that creates a shape in blender in the test, export it, import it, and poke around the result to see that I got what I wanted. Way easier than trying to create shape data in code. That's critical because I can't do this without decent automated tests. 

 

Then I thought I should maybe rewrite the code a bit. I am translating the blender data model into simple python lists and dictionaries, manipulating them, then shoving them into a buffer to pass off to nifly, which puts them in its own data structures before writing them out. So I spent a long time exploring blender's bmesh system only to find out that a basic function I needed--switch a polygon from using one vert to another--wasn't available in bmesh. Which is freaking annoying since the whole reason for that system is to give the coder an easy way to manipulate meshes. And also too this whole part of blender is almost completely undocumented, so it's a bunch of poking through the data model in the interactive python window. 

 

So anyway I gave that up for a bad job and really, it's quite possible that what I'm doing is faster than leaving everything in bmesh, because I'm just doing native python list manipulation without all the blender baggage.

 

Right now, this system is blazingly fast, at least compared to other export/import. It will slow down as I add actual necessary features, but I expect it will have performance on the order of OS. 

Link to comment

×
×
  • Create New...

Important Information

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