Vertex Animated Meshes

Have you ever wanted to make your own animated meshes such as the CTF Flag, or the box straps in AS-Convoy? While characters for UT2004 are made using bone animation, the older method of vertex animation is still useful for creating effects that bone animation can not. This tutorial will go through the entire process from making the mesh in 3D Max to importing it and placing it in your level. Let's get started!

What You Will Need

You will need UT2004 and 3D Max installed, obviously. In addition to that you will also need a small program be Legend Entertainment called 3DS2UNR, which we will need for converting the mesh to a format Unreal can understand.

Download 3DS2UNR

Creating The Mesh

Open up 3D Max. For this tutorial, I will be using a simple Bagel for the mesh, so click the Torus button in the right toolbar and create the mesh in any of the viewports.

IMPORTANT - Vertex animated meshes must be created within a 256 unit bounding box, so no part of the mesh should ever go beyond a range of -128 to 128 in any of the axes even while animating, otherwise it will not be converted by 3DS2UNR.

Now that we have our Bagel, we will texture it real quick before we do the animations. It's much easier to do it now before it gets all deformed. Click on the Material Editor button in the top toolbar.

In the Material Editor you can see that the first sphere is selected. Click open the Maps tab and click on the Diffuse button.

In the window that pops up, double-click Bitmap and find the texture that you want to use.

Once you do that the material will appear on the sphere. In order to show it in the viewport, we need to click on the Show Map In Viewport button.

Now just click on the sphere and drag it over to our Bagel. It should now be textured in the 3d Viewport (if not, try hitting F3).

Now we're going to properly UV map it. Make sure you have the bagel selected, and click on the Modify tab in the right toolbar (looks like a curved pipe next to the arrow tab). In the Modifier drop down, select UVW Mapping.

For this tutorial I'm going to leave it at the default mapping that it gives it. If you have a more complicated mesh you can use the Parameters rollout in the right toolbar to adjust it, or use Unwrap UVW if you want to get it exact. There are tutorials that come with 3D Max that can take you through the steps for the best method of UV mapping.

Now for our animation. First I'm going to go back in the Modifier list and select Squeeze from the dropdown list.

Now hit the Auto Key button in the bottom toolbar to set Max into animation mode.

Now let's slide the timebar just below the viewports to frame 30.

Go to the Parameters rollout for our Squeeze modifier and change the Radial Squeeze amount to 6. You should see the change in the viewports, as well as markers appearing on the timeline and an indicator appearing around the Amount sliders. If you slide the bar back and forth, you can see it animating. For the rest of the animation we'll just copy the first marker to frame 60. To do this, hold Shift and click on the Frame 0 marker, then drag and drop it onto frame 60.

IMPORTANT - None of the polys of your mesh should EVER get reduced to zero area (vertices at the same location or along a single line). This will give you errors when we try to compile it and it won't import. For example, scaling the entire mesh to 0% would make all of the polys zero area.

Once that is done, we're ready to export our animation. There are two ways of doing this, but the old method is the only one that I've found to be reliable. ActorX supports vertex animation, but it seems like every new version breaks it and I didn't have any luck with the current one (215 as of this writing). For this tutorial I will use the old but reliable method of 3ds2unr.

First let's give our Bagel a name. In the right toolbar you should see it labelled Torus01. Let's change this to MyDealie00. The 00 at the end is important for 3DS2UNR's conversion process, as it will look for the numbers at the end when it puts the animation into sequence. Now hit Tools >> Snapshot.

In the window that pops up, we need to change a few things. Set the snapshot to Range, and the From and To to 0 and 60 since those are the frames we're using for our animation. In the Copies box, set it to 61 (60 frames + 0 counts as a frame). Make sure the Clone Method is set to Mesh, then hit Ok. You will see the duplicates being made in the viewports, and after it is done the Snapshot window will disappear. Now we have 61 meshes, all named MyDealie00 through MyDealie60.

Almost done in Max! Hit Edit >> Select By >> Name (or hit the H key) to bring up the Select Objects dialogue, and select all of our MyDealies except for the MyDealie00 one (3ds2unr will give you a warning if you select the 00 mesh as you will see in my DOS pic later, but there's no real negative effect of selecting it since it will ignore it anyway).

Now that we have our meshes selected, hit File >> Export Selected. Navigate to the UT2004 folder, and create a subfolder called mylevel. Save our mesh as a .3DS file in the mylevel folder. When it asks you if you want to preserve Max's texture coordinates, leave it checked (we wouldn't want it to lose our UVW mapping!)

Now we're done with Max. If you want to save the mesh for future alterations, hit Undo until you get to the point just before we made the snapshot and then save it, and close out 3D Max.

Converting And Compiling

If you haven't already downloaded 3DS2UNR, Do it now, this is where we need it. Copy the .exe into the mylevel folder where our mesh file is.

For 3DS2UNR to work properly, it needs a directory structure created for it to use. In the mylevel folder, create subfolders called classes and models.

If those folders are not present it will give you an unknown exception error in 3DS2UNR.

Now we need to open up a DOS prompt, so hit the Windows Start button >> Run, then type cmd and hit enter. We need to navigate to our mylevel folder, so we use Change Directory (cd) commands to get there. Using cd\ returns you to the root directory (C:), then we use cd commands to get to the mylevel folder. Once we're there, we need to set 3DS2UNR's project directory so it knows where to put everything. Type 3DS2UNR -setproj and select the mylevel folder.

Now we can convert our mesh. Use the command 3DS2UNR MyDealie MyDealie.3ds to convert it. The first MyDealie tells it what we want the final class to be named, and the second one gives it an animation file to convert.

If we wanted to do more than one animation for our mesh, we could go back into Max and make a different one, then Snapshot it and export it as MyDealie2.3ds or whatever we wanted to name the animation. Be sure not to change the name in the right toolbar though. Then we would just add an extra .3ds command at the end of our conversion to make it import both animations, or more if we wanted.

Now we're done with 3DS2UNR. Go into the mylevel/classes folder and use Notepad to open up the MyDealie.uc file that was generated. There's a few things that we need to change, and a few things that you might want to add. Let's take a look at the first section of it.

"Expands" was used in UT99's class system, but doesn't work in UT2k3/4. We need to change that to "extends" so UT2k4's code system will recognize our class. In addition, add "placeable" before the semicolon at the end so we can actually add it to our map from the Actor browser. We don't need to do anything to the MESH IMPORT, MESH ORIGIN, or MESH SEQUENCE sections, so we'll leave them alone and take a look at the next section.

Exporting our mesh from 3D Max and converting it with 3DS2UNR screwed up the texture name, type, pretty much everything having to do with our texture except for the UV mapping. We'll take care of it once we import our mesh into UEd, so for now let's delete these two lines.

Now we need a way to get our mesh to animate. It's just going to sit there if we import it now. There are a few ways we can do this. The first one is to just have it automatically loop the animation over and over. To do this we need to add a PostBeginPlay function below all the #exec lines but above the DefaultProperties section.

PostBeginPlay() is called on every actor in the level right before the level shows on your screen, so it's perfect for setting it to play the animation. Within that function, the LoopAnim command tells it to play our animation. If we wanted it to play one of the other animations we made for it, we would just change 'MyDealie' to 'MyDealie2' or whatever other animation we made. The number after the comma is an optional rate, if we wanted it to play the animation slower or faster than it did in Max.

But what if we want to trigger it for the animation to play? To do that, we would just add an Event Trigger function.

Whenever something is triggered, this function is called. Instead of using a LoopAnim, we use a PlayAnim command here to have it just play the animation once. We could change it to LoopAnim if we wanted it to keep going once triggered though.

What if we wanted both? Would there be a way to have some of them triggered, and some of them just automatically looping? For that we would have to put both functions in, and add a few lines.

the var() bool line at the top puts a True/False variable into our actor that we can access in its properties. Then we add an if() statement in the PostBeginPlay function to check if that is true. If we set it to AutoLoop, then it starts looping, otherwise it ignores the LoopAnim command.

There is one other thing that you may want to add in the default properties.

bEdShouldSnap makes it snap to the grid the same way static meshes and BSP do.

Now we're done editing the .uc file, so save it and close it (make sure it keeps the .uc extension). Now we're ready to compile our class into a .u file. Go into the UT2004/system folder and open up UT2004.ini. Hit Edit >> Find and look for "EditPackages". Close out the Find window and scroll down to the end of the EditPackages list. Make a new line under it and add our mylevel package.

This tells our compiler to look for these .u files and create them if they don't exist. Open up another DOS prompt (Start >> Run >> cmd) and navigate to the UT2004/system folder. Type "ucc make" and UT2004's code compiler will go through and make our mylevel.u file for us.

Success! We're done with DOS, so we can close that out. Go back into the UT2004.ini file and delete the EditPackages=mylevel line. We don't want to make the editor dependent on that file, otherwise it won't load once we delete it.

Importing And Placing

Open up the Editor and load your level. Go into the Actor Browser and hit File >> Open Package, and open our mylevel.u file.

Now to set the default texture it uses, right click it and hit Default Properties.

Select a texture in the texture browser, then go to Display >> Skins and hit Add, then Use. This will set the texture as the default. Close out the default properties and add it to our level!

Testing it depends on how you set up the functions earlier. If you put the bAutoLoop variable in, just double click it to bring up its properties and go into the MyDealie tab.

Set it to True then run the level and it should be animating. Yay!

If we set it to be triggered, we'll need to add a trigger and set it's Event to our MyDealie's Tag.


Once our mesh is in and working, save the level and close UEd. One last thing we need to take care of. Go into the UT2004/system folder and delete the mylevel.u file or move it to another folder for future use (ONLY do this once the mesh has been placed in the level. Only things that are in use are kept in the level's mylevel package). The mesh is saved in the map file itself at this point, so this file is no longer needed and shouldn't be kept in the system folder.

Well, that's it for this tutorial. Vertex animated meshes can do some really nifty things that bone animation couldn't without hundreds of bones. Good luck!

UDN - Unreal Model Importing
Unreal Wiki - Weapon Modelling and Import