Skyrim loader

I’ve created generator for java classes reading nif format (Gamebryo one, used in Skyrim and many other games). As a proof of concept, I have added a small renderer.
Only basic things are supported in renderer for now - triangle meshes with diffuse+normal textures and position nodes for them. Nif loader on the other hand should support all games out there - it is generated from niftools xml and is fully dynamic based on file version/format.

I have a lot of cleanup to do and I will probably need to add bsa loader - expanding all textures to disk is a painful process (and fails due to case sensitivity issue with FileLoader).

Some screenshots below.




16 Likes

Nice :slight_smile:

Pretty cool.

Amazing!

This is awesome. I’m guessing just like with World of Warcraft models and the like. as long as we load them in jME3 strictly as a model loader and not for redistributed game products, we can show off all the models (and amazing scenes!) we’d like?

I have implemented loading directly from bsa files and improved handling on some models, so all static models which I have tried are loading correctly now (of course, no special shaders yet, no emitters, emissive textures, fur etc etc)

Next task - animations. They are non-trivial, with like 3 levels of indirection for bone indices, but hopefully should work.

superb!!! now i will be making skyrim 2 :smiley: once i tried to extract Oblicion (oblivion is previous elder scrolls game), so it was a real headache

[video]http://www.youtube.com/watch?v=t_Zkuakvm0E&hd=1[/video]

I wonder how bright it will be on your screens. For me in jme3 and when watching video it is just right - dark metallic green. Youtube screenshot (one before you press play) shows very bright, oversaturated green. Anyway, it was supposed to be dark metallic :wink:

1 Like

Looks fine when I play it:

…I’ve noticed youtube doing that weird coloring thing for the embedded video thumbnails lately. Kind of odd.

<cite>@pspeed said:</cite> I've noticed youtube doing weird things.

There, I fixed it for you. :wink:

Yeah the preview is a bit funky but it looks just like it’s supposed to once you press play. Wow, I can’t wait to see complete Skyrim scenes, this is gonna be awesome!

Cool. From the FileLoader issue I take it you don’t use the jME API.

Any1 up to making this a “real” jme loader class? :slight_smile:

1 Like

[java]
assetManager.registerLocator(“c:/gry/steam/SteamApps/common/skyrim/Data/Skyrim - Meshes.bsa”,BsaFileLocator.class);
assetManager.registerLocator(“c:/gry/steam/SteamApps/common/skyrim/Data/Skyrim - Textures.bsa”,BsaFileLocator.class);
assetManager.registerLoader(NifLoader.class, “nif”);
[/java]

It is as much JME3 as possible. This works ok for static models. Unfortunately, for animated models, you need to compose data from multiple files - skeleton, mesh and 1 for each animation. For that, I’m using only Locator part, converting and composing pieces by hand.

Still, skeleton loaded is jme3 skeleton, animation is done by AnimControl+ jme3 Animation + Skeleton Control, textures are loaded from plain assetLoader (which uses BsaFileLocator to load input streams).

I’m not sure if it will be ever possible to just automatically load model with animations with one call to assetLoader.loadModel - at least without going through artificial config file which will specify number of other files to merge.

BsaFileLocator works properly because I have made it case insensitive. It is good enough for testing, but to properly load data from Skyrim data dir, expanded overrides also have to be managed - and they have random case versus what is specified in data files. Only way to work around that would be to provide case-insensitive FileLocator.

1 Like

Cool, but then you will have to deal with the fact that the jME asset loader is nominally case sensitive. Some loaders might react differently, especially file loaders as the filesystem has to support this feature when using files.

Generally using absolute or system file paths is strongly discouraged to maintain true platform independence, loaders should work from any input stream the assetManager can deliver. For iOS for example theres no files at all, its binaries that are loaded via the classpath loader. Also for the SDK normal behavior is important to allow for all managing options. Though I admit some implications of “path/filename == asset name” are sometimes hard to implement properly, but nothing was yet impossible.

Yes, I understand - and it is not using absolute filepaths anywhere in processing, but obviously FileLocator has to be configured with real filepath. All loaders I have implemented are working from streams (they are actually working from byte arrays, so they fully load stream into one before progressing - too much hassle to make it truly streaming).

Loaders are generally not a big issue here - locators are. If we are to support leeching directly from Skyrim installation, CaseInsenitiveFileLocator will be needed, implemented in the way it can also work on linux (probably getting list of files/dirs and resolving them manually with ignorecase). In any case, it is not a showstopper - BsaLocators are good enough unless you want to use overrides from Skyrim mods.

@abies said: I'm not sure if it will be ever possible to just automatically load model with animations with one call to assetLoader.loadModel - at least without going through artificial config file which will specify number of other files to merge.
How about using custom AssetKeys? You can pass additional information to the loader using the custom fields in the key.
<cite>@Momoko_Fan said:</cite> How about using custom AssetKeys? You can pass additional information to the loader using the custom fields in the key.

In theory yes, I can make a subclass of AssetKey and put extra data there - but I don’t see a big benefit here. I feel the power of saying
[java]
model = (Node) assetManager.loadModel(“meshes/Landscape/Trees/TreeAspen01.nif”);
[/java]
which works currently for non-animated models. But for animated model, I would need something like

[java]
model = (Node) assetManager.loadModel(new NifAssetKey(
“meshes/actors/giant/character assets/giant01.nif”,
“meshes/actors/giant/character assets/skeleton.nif”,
“meshes/actors/giant/animations/combatidle01.kf”,
“meshes/actors/giant/animations/combatidle02.kf”,… further animations));
[/java]

It anyway requires a special non-standard code. Isn’t it better to just have

[java]
NifModel nmodel= new NifModel(assetManager);
nmodel.loadSkeleton(“meshes/actors/giant/character assets/skeleton.nif”);
nmodel.loadSkin(“meshes/actors/giant/character assets/giant01.nif”);
nmodel.loadAnimation(“meshes/actors/giant/animations/combatidle01.kf”)
nmodel.loadAnimation(“meshes/actors/giant/animations/combatidle02.kf”)

Node model = nmodel.generateModel();
[/java]
? With that approach, you could dynamically load animations as needed instead of specifying them upfront in AssetKey.

Anyway, wrapping NifModel-like class in Jme3 loader accepting some custom key is trivial, so I will do that if somebody asks for it - atm I just don’t see to much benefit (as opposed to static models, which you can drop-in replace as simple string-based asset in places not aware it is Nif/Skyrim resource).

Do all characters share the same animations? I guess not, since you cannot make a spider animate like a humanoid … Then there has to be a way to determine that the skeleton from a model is compatible with a skeleton from an animation? Maybe this checking can be performed ahead of time and written into some database file, mapping models to available animations.

I suppose there is some metadata hidden somewhere in Skyrim data files, but I have not looked very closely. Animations are hard things - I’m able to read only part of it (keyframe animations), there is plenty of other stuff related to havoc kinematics which is black box (but not needed for normal animation).
Additionally, there is kind of basic scheme they seems to follow - you will have “meshes/actors/<name_of_type>” and then multiple models below, but all sharing same skeleton - and skeleton is what determines if animation is compatible or not. Still, it is bit too much logic to hardcode into basic asset loader, I think about possibly doing utility class on top of it.

In meantime, I have managed to load and display Oblivion models. Animated ones are broken atm, but static ones looks proper.

I have checked work in progress version at
https://subversion.assembla.com/svn/vmat/nifloader/trunk/

You may want to run test program
net.virtualmat.nif.jme3.test.NifTest
and pass a single argument to it being your Skyrim installation directory (something like “c:/games/steam/SteamApps/common/skyrim” or whatever it is for you).

If you don’t have tonygodgui project checked out, just comment our entire ‘createSelectors’ method and manually execute the code from modelSelector.onChange on one of model paths.

It is very much work in progress - the actual exercise was in writing nif loader generator, jme3 code around is just a quick hack to make sure that I’m interpreting nodes properly. NifConverter class is a mess of spagetting code - look at it as a research in motion rather than final version. I don’t want to make it too pretty until I understand the nif structure more.

Animated models with skeletons are disabled at the moment - they require manual step with unpacking and converting havoc files into keyfile animations - I will automate it later, but for now it is just disabled.

Many models are not working or are displaying with errors - but probably around 50% look quite good.

Slider in top left of the screen is experimental ‘snow’ shader. If you uncomment moss texture in slider code, it will emulate ‘moss’ instead of snow - I think that in Skyrim they are putting moss from north side instead of up, thats still left to do (and anyway, snow will break if you would rotate model).

3 Likes