LarryG on 6/9/2013 at 22:40
Jointed objects are a little tricky, and (
http://thiefmissions.com/lpg/VHots_Axles.html) Schwaa's VHOT and Axels tutorial, excellent as it is, will only take you so far. So this is my attempt to explain what I have learned about the subject. Hopefully between what Schwaa has to say and what I have to say, you'll be successful in building your own jointed object models in whatever 3D modeling tool you use.
Basic Concepts
* A jointed object has only three part types: the base object, the sub-object, and the axle object.
* The base object is the part of the jointed object which
does not move.
* The sub-object is the part of the jointed object which
does move.
* The axle object tells how the sub-object moves with respect to the base object.
* The axle object is always two points with a line between them.
* There are only two types of axle objects: rotation and translation.
* You can have multiple levels of sub-objects. That is, a base object can have multiple sub-objects attached to it via axle objects, and it can have sub-objects which have their own sub-objects attached to them via their own associated axle objects! You might want to think of these as sub-sub-objects. I can't stop you. The most sub-object levels I have ever used successfully is three: base object, sub-object, sub-sub-object, and sub-sub-sub-object. I think that theoretically 5 might be possible, but I have never seen it done.
* The names associated with these objects define which is what. [**** IMPORTANT ***]
* Positioning the parts of a jointed object such that they are acceptable to bsp.exe can be very tricky!!
* The more levels of sub-objects that a jointed object has, the trickier it is to build a model acceptable to bsp.exe.
Naming Jointed Object Parts
* For the base object, only the first two characters of the name are significant. For example, if you name your base object,
Object, the "real" name as used by bsp.exe in creating a bin file is just
Ob. The rest of the characters in the name are ignored. More about this in a minute.
* If your jointed object has only a base object and one or more sub-objects attached to it, then the name you give to your base object can be whatever you want. However, if your jointed object has more than one level of sub-objects, I strongly recommend that you name it
Aa. More about that later.
* Axle object names follow one of two specific patterns:
@Xjjobnnnn or
@Zjjobnnnn:
* the
@ sign indicates that the name is a special name; all axles, sub-objects, and vhots must begin with
@, and only axles, sub-objects, and vhots.
*
@X means rotating axle
*
@Z means translating axle
*
jj is one less than the joint number you want to refer to it by in DromEd (00=Joint 1, 01 = Joint 2, 02 = Joint 3, etc.)
*
ob is the two character name of the base for the joint
*
nnnn is the degrees of movement that you want bsp.exe to check for interferences in a special code (0000 = 0°, 1250 = 45°, 2500 = 90°, 5000 = 180°, 7500 = 270°, 9999 = 359.964°). [I recommend that you don't have bsp.exe do any checking and always use 0000.]
So, if you ran across an object in a model with the name
@X03Aa2500, you would know right away that it is a rotating axle which would be referred to in DromEd as joint 4, whose base object was named with Aa as the first two characters of its name, and that only a 90° movement interference check is desired. Similarly
@Z00Ob0000 is a translating axle referred to by Joint 1 in DromEd, with base object named Ob-something, and no interference check is desired. Simple, right?
* sub-object names all must be of the form:
@Sjjob*
@S indicates that this is a sub-object
*
jj is the joint designator for the associated axle object that it moves according to
*
ob is the sub-object name reference. Generally only two characters are used as only the first two characters are significant for bsp.exe, but I suppose you could use a longer name.
So, if you ran across an object in a model with the name
@s01bb, you would know that it was a sub-object which moved according to the axle object with
01 as the joint designator and that it was referred to as
bb if referenced by any other objects (say by the joint for a sub-sub-object)
With me so far? Let's look at a couple of examples. The first is a shipping crate with a movable lid and on the lid is a moveable hasp.
[ATTACH=CONFIG]1788[/ATTACH]
This shipping crate has a base object
aa (the bottom and sides of the crate) which has an associated axle object
@x01aa0000 (the hinges for the lid). This axle is associated with Joint 2 in DromEd, and is a rotation axle with no interference checking done.
There are two sub-objects for the shipping crate. One, the lid of the crate, is a sub-object to
aa, named
@s01bb. You know that it moves with respect to Joint 2, and since Joint 2 (
@x01aa0000) is associated with
aa, you know that the lid hinges off of
aa. The second sub-object is the hasp of the lid's fastener system. It hinges with respect to the lid, and not with respect to the bottom of the crate. We know this by looking at its name and the name of its axle:
@s00cc and
@x00bb0000. You know that the hasp uses the Joint 1 axle object, and looking for that we see
@x00bb0000. This name says that this axle is associated with bb (the lid) and not aa (the crate bottom). So
@s00cc is a sub-sub-object.
Diagrammatically the setup is:
base --axle------------> sub-object --axle----------> sub-sub-object
aa -
@x01aa0000 --->
@s01bb -
@x00bb0000->
@s00ccThere are a couple of interesting points that this example illustrates:
* The joint assignments are arbitrary. The first joint off the base does not have to be 00. It can be any legitimate joint number, 00 through 05 (Joint 1 through Joint 6). In this case the lid hinges off of Joint 2 and the hasp on the lid hinges off of Joint 1.
* While the sub-object's name clearly associates it with a axle object, and the axle object's name clearly associates it with the
base object, it is a best practice to name such linked object parts alphabetically. aa->bb->cc. When we come to multiple sub-objects off of a single base, you will see that you skip a name to indicate that both sub-objects are off of the same base: aa->bb and aa->dd. cc is skipped since that would mean that cc was off of bb and not aa. Get it? More later on this later. But it is important to getting multiple joints to work.
Here's another example. This is a railroad semaphore signal. The head turns and the flags attached to the head raise and lower.
[ATTACH=CONFIG]1785[/ATTACH]
As discussed above, the
Dd designator is skipped for this model since
Bb has two independent sub-objects,
Cc and
Ee. Use of
Dd instead of
Ee for the second flag would indicate that it was a sub to
Cc, which it isn't. Make sense? All I can say is that this alphabetical naming seems necessary to get multiple jointed objects to work. If you have just one joint, you can name the base object and sub-object whatever you want. That seems to work just fine. But with multiple sub-objects I strongly suggest you stick with Aa, Bb, Cc Dd, etc. with appropriate name skipping. Not to do so seems to cause troubles.
Another point, about axles this time. While axles are invisible in-game, they are not insubstantial. That is, they can change the physics box about your object. The points at the ends of the lines count towards that calculation, so if you want the axles not to make your objects bigger, keep them inside of the solid portions of your object. In the semaphore above, this was not done. You can easily see that the axle
X00Aa0000 sticks down below the base of the semaphore at the bottom and above the head of the semaphore at the top. While that makes things easy during construction, it is a good practice to move those points to be inside instead before generating your bin.
This is a cell door, with a translating bolt instead of the normal rotating handle. When you pick the lock, the bolt visibly withdraws indicating the door is unlocked.
[ATTACH=CONFIG]1786[/ATTACH]
You know the bolt moves linearly because of the name of its axle
@z00aa0000. Joints on doors for handles (and bolts) have to use Joint 1. That's what the StdDoor script is looking for to move the sub-object about the joint.
Another thing to note is that a door is a special case. It doesn't need a joint for the door to pivot about. The hinging of the door is taken care of by the set-up on the door (Door>Rotating properties) and the StdDoor script.
Jointed Object Modeling Best Practices
* Sub-objects cannot intersect base objects or other sub-objects. Give plenty of visible separation between them, and then a little bit more. Fortunately in most situations this extra spacing is totally invisible in-game. You think it would be obvious, but it's not. So spare yourself some grief and space thing out more than you think is necessary. If bsp.exe rejects it, then you've got something intersecting something it shouldn't or bsp.exe thinks something is / will intersect something it shouldn't. Which leads to my next bit of practical advice:
* Test things out one joint at a time. If you want to have a 6 jointed object (why? why? why?) build the base object and the first sub-object with its associated axle object, and immediately see if you can get it to pass bsp.exe. Then progressively add one sub-object and axle object at a time until you get all of the joints working.
* If bsp.exe chokes on the jointed object, try renaming things so that the model is just a normal model and not a jointed one. Then try bsp.exe again. The problem may not be with the joint(s) but elsewhere in your modeling. If bsp.exe is OK with your model without the special joint names, then you know that it thinks something is intersecting if things move as you have designed them. Go back and read best practice 1. I really meant it. Sometimes a small movement in the axle left, right, forward, back, up, down may be all it needs to make bsp happy. Sometimes it can take hours of playing around with moving the problematic sub-object and/or axle object. Sorry. That's just the way it is. Following best practice 2, will help you focus in on just what part of your model is causing the issues.
* I believe that axle rotations follow the "right-hand rule"
[ATTACH=CONFIG]1787[/ATTACH]
so theoretically if you construct the axle line from point A to point B, that should be interpreted as a vector from A to B, and if you line up your right thumb to that vector, you should know what the positive rotational movement is by looking at how your fingers curl on that hand. But I always forget to do that, only to find when I import the bin into the game that my hinge rotates opposite of what I want. So I have to go back and flip my axle 180 degrees and try again.
* Don't be too ambitious at first, Do a few single jointed objects successfully before you try multiple joints.
More on using jointed objects in DromEd to come ...
Edit: One more thing that I have learned: Always define your joints in order, starting with Joint 1 (axle 00) and continuing in sequence to Joint 2, Joint 3, Joint 4, Joint 5, and Joint 6. Do not skip joints in your joint definitions. No gaps. DromEd's Tweq > Joints doesn't like it when you skip joints. If you have a three jointed model, make the joints Joint 1, 2, and 3. If you have a one jointed model, always make that joint numbered as Joint 1. If you deviate from this, your joints may not work properly or at all. And you could end up endlessly trying to fix the geometry of the model when all that is wrong is that you named your axles wrong. It makes no never mind which axle is which, but you must have a 00 axle (joint 1) and each subsequent axle must be in sequence up to 05.