Sunday, 23 April 2017

Urho I76 Model Viewer

Loading Up Models

The next thing to do under Urho3D is to load up the models for I76 assets.

The Hard Way

The hard way to do this is to manually generate an Urho VertexElement array and attach the model vertex and normal data, linking a VertexBuffer and IndexBuffer through a Geometry element.

This approach works, and there's an example of it in the sample application, but it's fiddly and my implementation is error prone. So let's not do that.

The Easier Way

The simplest way to do this is to use the AssetImporter tool from the Urho3D distribution. This can take an OBJ format file, which we can generate easily, and produce output files that Urho3D can load directly. It adds an extra step, but simplifies the process.

So we generate the OBJ file format files as we do in the existing C++ code, and then use the fileSystem.SystemRun() call in AngelScript to shell out to the AssetImporter binary. There's code in the default Urho application that we can use more or less directly for a prototype, that handles assembling the command line and also tacks on the .exe extension for windows. We'll replace this at some point, but for now let's just use it as is for the demo.

Otherwise there really isn't much clever here - we reimplement the ZFS unpacker in Angelscript to extract the resources, then we can view either individual models from GEO files, or complete vehicle assemblies from the VDF file. Extracting from the ZFS takes several minutes, and so the app should be run windowed, and the terminal will report the progress of the unpack. We could implement a background loader, but it's not worth the effort for a run-once process like this.

The only other annoyance is that the floating point output from AngelScript threw up errors with the AssetImporter by default - small values will be represented by scientific format (e.g. 3.3021e-05) and the importer doesn't like some of these, and there didn't seem to be a way to format the output more precisely. So we spot small values and treat these as exactly zero when we write them out.

Here's a tarball attached with:

  • AssetLoader: - Load a ZFS file, and unpack the ZFS itself, embedded PAK files and do the basic conversion for GEO to objects and VQM to texture images.
  • ObjLoader: - View individual object files. Does on the fly conversion.
  • CarLoad: - Load VDF files - this has some issues (the tendency to mess up interior geometry fragments, and some normals are iffy), but it's functional enough to pull out some basic geometry for the composite models.

The conversion process just applies a default image file for testing at present (whichever image you copy into Textures/test.png), and requires a defaultmat.xml Material file. It's lacking basic error checking, but as a proof of concept it holds together.

Also this will not work on the Nitro ZFS, since AngelScript doesn't know how to decompress the LZO compressed files without the platform specific libraries.

Otherwise, it mostly sorta works...

AngelScript: Some Thoughts

Having used AngelScript for a few days then the thoughts that keep cropping up are

The Good

  • Fast Prototyping.
  • Straightforward UI & 3D implementation.
  • Feature rich primitives.
  • Syntax: maps neatly to C++ versions.

The Bad

  • No debugger: This is a real PITA. The code has wound up with debug Print calls scattered around.
  • Silent Failures: Some setup errors leave things silently non functional, rather than producing more obvious error reports.
  • Slow: Although the heavy lifting is mostly done by the core engine having scripts generate things like texture images and bitmap resources can result in major slowdowns.

The Ugly

  • Ownership: The Urho Angelscript version uses reference counting for memory management, but without a debugger it's easy to lose track of what references are valid at times and leak resources (such as open file handles).
  • Not Quite Vanilla AngelScript: Enough custom types that the default AS docs don't always seem to apply directly or help understand Urho's use of the language.
  • Documentation: It's there, but not always useful, and the examples take some parsing to understand: it could be better.
  • No Printing Format control? I couldn't figure out how to persuade floats to output in a specific format, hence the low value rounding utility.