At its most abstract, NWN Armory is a quick application that performs renaming, scaling, rotating and translating on NWN PC model parts to generate other model parts.
Why would you ever want to do this? It is intended for two main reasons although there may be other applications for it as well
How do you make it work?
To create a race model from a human template, it is easy:
To create all armour models for a new race , you need to do a little more work:
The transform file is fairly simple but, I think, powerful (this is why the tool may be used for other duties as well, such as simply renaming models without changing them). Standard.ini is supplied with this program and contains the standard racial transforms. Sample.ini is an example of different transforms that can be used with this program.
This is from the sample.ini file example.
; This .ini is a sample to show how to set up different examples
;
; By Eligio Sacateca, May 2003
;
; Instructions
; Specify the number of transform groups with ntransforms.
; The program will only read this many transforms even if
; you include more in this file.
;
; For each transform, create an index row [s>TRANSFORM#<]
; These do not have to be in order (altho they are easier
; to keep track of if they are, obviously).
;
; If you skip a row the corresponding group will not match
; any input files so it should not hurt anything (it won't
; help either but if you delete one you don't need to go
; back and renumber everything).
;
;
; The format of each group is:
; match= : if this string matches the input source model name, this
; group will be applied against the input file to produce an
; output file. This string uses globbing where a '?' is a wildcard
; and will match any single character while '*' is a full glob
; wildcard and will match any number of characters. Examples:
; abc* matches abcdef
; abc??? matches abcdef but not abcdefg ; abc*f matches abcdef and
abcdeanythingf
; abc does not match abcdef
;
; substitute= : the file and model name of the new file will consist
; of the input name, modified by substituting characters in this
; string against it. a '?' is a wildcard and will not change the
; input string at that point. A '*' is a full glob wildcard and
; will not change any more characters past the end of the input
; name. If the input model name exceeds the substitute string in
; length (after taking into consideration wild cards like '?' and
; '*'), excess characters will be truncated. If the input model
; is shorter, extra characters from the substitute string will be
; appended at the end. Examples:
; abcnopqrs to defghi gives abcnopqrs
; abc to defghi gives abc
; abc? to defghi gives abcg
; abc* to defghi gives abcghi
; abc*n to defghi gives abcghin ; ??abc to defghi gives deabc
;
; scale=(x, y, z) : x, y and z axis scaling respectively. If you
; don't put in a scale parameter for a group, it defaults
; to (1, 1, 1) (i.e., no scaling).
;
; rotate=(x, y, z) : x, y, and z axis rotation respectively. If
; you don't put in a rotate parameter for a group, it defaults
; to (0, 0, 0) (i.e., no rotation).
;
; translate=(x, y, z) : x, y, and z axis translation respectively. If
; you don't put in a translate parameter for a group, it defaults
; to (0, 0, 0) (i.e., no translation). Translation is the only
; parameter with absolute values so don't forget that most models
; are scaled by 100x when viewing them in Gmax or Max so if you
; experiment in these tools to get the right values, don't forget
; to reduce the translations appropriately.
;
; translate=(x, y, z) : x, y, and z axis translation respectively. If
; you don't put in a translate parameter for a group, it defaults
; to (0, 0, 0) (i.e., no translation).
; This is a parameter with absolute values so don't forget
; that most models are scaled by 100x when viewing them in Gmax or
; Max - if you experiment in these tools to get the right values,
; don't forget to reduce translations appropriately.
;
; position=(x, y, z) : x, y, and z axis specification for the position
; parameter within the model file. For armor parts, the position
; parameter identifies the pivot point for the model.
; This is a parameter with absolute values so don't forget
; that most models are scaled by 100x when viewing them in Gmax or
; Max - if you experiment in these tools to get the right values,
; don't forget to reduce translations appropriately.
;
; minimum=(x, y, z) : if a vertex is outside of the minimum
; x, y, and z values, it will not be transformed. I don't expect
; this and the maximum= parameters to be used much but they can
; be set up to do selective transforms on vertices. I created
; these parameters so that I could scale parts of a model differently
; than the rest of the model.
; This is a parameter with absolute values so don't forget
; that most models are scaled by 100x when viewing them in Gmax or
; Max - if you experiment in these tools to get the right values,
; don't forget to reduce translations appropriately.
;
; maximum=(x, y, z) : if a vertex is outside of the maximum
; x, y, and z values, it will not be transformed.
; This is a parameter with absolute values so don't forget
; that most models are scaled by 100x when viewing them in Gmax or
; Max - if you experiment in these tools to get the right values,
; don't forget to reduce translations appropriately.
;
; If the scale, rotate, and translate parameters amount to no
; no change, the program will just copy the input file and rename
; the model according to the substitute string. This is useful for
; copying and renaming models with no other changes.
;
;
; trotate=(z) : (new!) z-axis rotation of the
texture map. If
; you don't put in a rotate parameter for a group, it defaults
; to (0) (i.e., no rotation).
;
; tscale=(x, y): (new!) x and y axis
scaling respectively for a
; texture map. If you don't put in a scale parameter for
; a group, it defaults to (1, 1) (i.e., no scaling).
;
; ttranslate=(x, y) : (new!) x and y axis
translation of your texture
; map, respectively (that's right, you can now move texture maps
around).
; If you don't put in a translate parameter for a group, it defaults
; to (0, 0, 0) (i.e., no translation).
; This is a parameter with absolute values so don't forget
; that most models are scaled by 100x when viewing them in Gmax or
; Max - if you experiment in these tools to get the right values,
; don't forget to reduce translations appropriately.
;
; tminimum=(x, y) : (new!) if a texture
vertex is outside of the
; minimum x and y values, it will not be transformed. These is
; pretty much the same as the minimum and maximum values applied
; to texture maps.
;
; tmaximum=(x, y) : (new!) if a vertex is
outside of the maximum
; maximum x and y values, it will not be transformed.
;
; tbitmap=<bitmap name> : (new!) lets
you specificy that only texture maps
; for this bitmap will be transformed.
;
; That's it!
For the output file, each vertex is rounded to 7 decimals of accuracy. Which means after you scale by 100 to make them visible in-game, each vertex has 5 decimals of accuracy. I did this for three reasons:
The order of operations is important. It is scaling followed by rotation followed by translation.
Rotations are done successively and in VIEW coordinates. Let me explain that. It is the equivalent of
If you use other coordinate systems, your mileage will vary.
Note that rotation takes place about the origin only (0,0,0). Also, the program now scales, rotates and transforms the pivot point in addition to the other vertices. Usually it has a value of (0,0,0) so rotation and scaling do not generally affect the pivot point - only translation does.
Note the new texture map translation feature. I did this to create black weapons from default ones that use Bioware's standard weapon texture. It can be used for all sorts of odd things. No, really, it can. Just don't ask me to list the uses. There are, uhm, too many.
Most parameters have a default value so they do not have to be specified:
Please send bugs, either in the program or the standard.ini transform file, to eligio@cogeco.ca.
That stunning background image is batinthehat's Arcanoloth from the City of Doors initiative. Feel the leather. It's real. No, really, I swear it is.
All this stuff is copyright Eligio Sacateca, 2003. Well, most of it. Not the background image - it is bat's. Didn't I already tell you that?
All rights are reserved. All of them. Really. Whatever that means.
Having said that, I also give you permission to use it if you want for anything you want. As long as it is legal and doesn't get me in trouble - if you are going to do something illegal with it then you can't use it.
Oh, and feel free to email me if you want a copy of the source code.
Did I mention all rights were reserved? They are - notwithstanding the fact that you can use it for pretty much anything and you can have the source code too.
I think I'm obligated to tell you that there is no warranty either. Absolutely none. Zero. Zilch. This program may not do what it was intended to do and it certainly may not do everything or even anything you want to do with it. If you live in one of those weird jurisdictions where I can't offer no warranty, then I take back what I said about you being able to use this piece of software. You can't use it. Using it would be illegal. And if you sue my ass for coverage under a warranty like that, then I'll sue your ass for illegally using my software when I said you couldn't. And then where will we both be?
There. I no longer feel like my ass is hanging out there with a cold breeze blowing across it. Do you feel better too?
The problem is to find a method to get the exact transform matrices for scaling to the different races. If BioWare didn't use anything but the scale tool we could do it fairly quickly. Unfortunately I am told they did a little more than a pure scale/rotate. Apparently most parts consist of a scale and then a couple of vertices that are shifted in an unknown and totally inconsistent fashion. Most modelers I have talked to say they want the tool to do 98% of the work and then they will go in and tweak the last vertex or two by hand.
Other people smarter than I (i.e., Saep) are working on how to reverse engineer the base transforms by trying to solve the following system of equations:
vertex_i_
= TransformMatrix * vertex_i_basemodel
where vertex_i is the i'th vertex of a mesh.
The matrix should be 4x4, but certain entries are given:
| s r r 0 |
| r s r 0 |
| r r s 0 |
| t t t 1 |
where r means rotate, s means scale and t
means translate.
If we find a mesh with more than 12 vertices (should be easy) the system of equations is solvable anyway. Once we have this matrix we can simply scale any model.