Modeling props with Blender

From Valve Developer Community
Revision as of 20:18, 31 January 2006 by Rof (talk | contribs) (Complex collision models)

Jump to: navigation, search


It is possible to create static, non-animated props in Blender, along with appropriate physics collision data, in case Softimage is too much. This requires use of the SMD Exporter by Pelle Johnsen. This exporter does not support skeletons, multiple materials, or animations, but it does support hard/soft edges.

Note:It is assumed that the reader knows the basic functions of Blender. At the very least you must be comfortable with creating simple models, applying UV texture mapping, and installing plugins. A working knowledge of how to compile models is a significant help.

Creating a basic non-solid prop

1. Create your model and texture it via UV mapping. The result should be a .blend file, plus all the TGA files you used as textures. The example used here is the PC Gamer UK mag I secreted all around de_dust_pcg (so I have pcgmag.blend and pcgmag.tga)

2. Having installed the SMD exporter plugin (http://asrc.pjohnsen.com/downloads/smd_export.py), export your model to a Half-Life 2 SMD file. In this example, I now have pcgmag.smd and pcgmag.tga - these are the files needed by the model compiling tools.
Model blender export.png

3. For a CS:S model, copy the SMD file into SteamApps/username/sourcesdk_content/cstrike/modelsrc and the TGA file(s) into SteamApps/username/sourcesdk_content/cstrike/materialsrc/models

4. The SMD we have already is just the reference model. We also need an additional SMD to declare the 'idle' animation. So, in a text-editor, create a file called 'pcgmag_idle.smd' (or some other name ending in SMD) and enter this as its contents:

version 1
nodes
0 "joint0" -1
end
skeleton
time 0
0 0.000000 0.000000 0.000000 0 0.000000 0.000000
end

5. The compile tools need a QC file containing model information. This is the file I used for pcgmag.smd:

$modelname pcgmag.mdl
$cdmaterials "models"
$scale 3.5
$surfaceprop "paper"
$staticprop
$body studio "pcgmag.smd"
$sequence idle "pcgmag_idle" fps 1

Note the scale factor, which I tweaked to get the magazine to appear at the right size in-game. Note also the $surfaceprop line, which sets the prop's material surface properties such as its surface friction and associated noises. Unlike a regular brush, any $surfaceprop set in the prop's material (.vmt) files is ignored; instead, it is set here in the .qc file.

6. The texture must also be converted into a VTF file just like any normal texture. However, it must include the $model declaration. This was the VMT file used for pcgmag.tga:

"VertexLitGeneric"
{
	"$baseTexture" "models/pcgmag"
	"$model" 1
}

7. Finally, change to the SourceSDK bin folder containing studiomdl.exe, and compile the model using a command like this:

studiomdl.exe "..\..\sourcesdk_content\cstrike\modelsrc\pcgmag.qc"

8. If everything went right, you'll get some nice output from studiomdl (look carefully for any errors), and you can now find the model in Hammer's model browser for use in-game.

Adding collisions

So far we have a basic model which can be used as a prop_static, but it has no solidity. At the moment, players, objects, and bullets will pass right through it. To prevent this, we need to create a collision model.

Creating a collision model is easy for a simple prop like this. We can use the same mesh as the reference model, but in Blender, select the whole mesh and hit "Set Smooth" (under the "Link and Materials" panel of the edit mode). We do this because the model compiler expects the collision model mesh for each convex part to have a single texture and be in one smoothing group. Now export the mesh as "pcmag_phys.smd". This is our collision model.

If the reference mesh isn't a simple convex shape, but is pretty close, build a collision model by making a cuboid roughly the same size and shape as the prop. (Note that the SMD export script requires a mesh to be UV-mapped, so you will need to apply a UV mapping to the collision model to export it, even though it will never be displayed.) More complex props may be very non-convex, a situation we will handle below.

Now we need to adjust the .qc file to add the collision model to the prop. Change pcmag.qc to this:

$modelname pcgmag.mdl
$cdmaterials "models"
$scale 3.5
$surfaceprop "paper"
$staticprop
$body studio "pcgmag.smd"
$sequence idle "pcgmag_idle" fps 1

$collisionmodel "pcmag_phys.smd"

We've just added the $collisionmodel line which refers to the collision mesh. Recompile the model, and when added as a prop_static in Hammer it will be solid. The player and other objects won't be able to pass through it, and if shot it will stop bullets and be marked by bulletholes.

Adding physics

Now we have a collision model, but the prop is still static: it can't move, or be affected by explosions or gravity. To do that, we need to add some physics data to the prop.

Edit pcmag.qc again so it looks like this:

$modelname pcgmag.mdl
$cdmaterials "models"
$scale 3.5
$surfaceprop "paper"

$body studio "pcgmag.smd"
$sequence idle "pcgmag_idle" fps 1

$collisionmodel "pcmag_phys.smd"
{
    $mass 0.5
}

$keyvalues
{
    "prop_data"
    {
        "base"	"Cardboard.Small"
    }
}


We've deleted the $staticprop line (since we're no longer making a prop_static), and added two sections: after the $collisionmodel line, we've added a section in braces, and a new $keyvalues section which specifies some prop data.

The section after $collisionmodel specifies the prop's mass, in kilograms, with the $mass command between the braces. I've set it to 0.5 kg here, which is a typical mass for an advert-laden PC magazine. The $keyvalues section specifies extra information for the model that the game engine can use - here, we set the prop_data for the model. I'm using the base prop type of "Cardboard.Small", being the closest thing available to a paper magazine. The prop data is required for any physically simulated prop, and sets things like the health and scale of damage of the prop from different effects. For a full list, see the scripts/propdata.txt file in source engine.gcf or counter-strike source shared.gcf.

Now recompile the .qc file using studiomdl.exe. We can now place the model as a prop_physics in Hammer. It will fall under gravity, collide with objects and the player, and will move around if shot at or caught in an explosion.

Complex collision models

So far, we can create a collision model for a simple convex object, such as a magazine or book. If we want to make a non-convex object, such as a table, we have to be more careful if we want the prop to collide with things as we would expect.

Blender-table1.jpg

Here's a wooden table made in Blender. Using subsurfaces I've given it a top with nice rounded edges, and tapered, cylindrical legs. I could make the collision model from the same mesh as the table itself, but that would be quite wasteful - collision meshes should be as simple as possible, so the physics engine has to do less work.

The black wireframe shows the collision meshes I've overlayed on the reference model, by making five separate objects in Blender. The table top is just a simple flat cuboid, and each leg is a tapered cuboid (or a truncated pyramid) following the form of the visible leg. In practice, it would probably be better to clip off the corners of the table top to match the reference model a bit more closely, but this is good enough for an example. I've placed the collision mesh objects in a separate layer in Blender from the visible model, so that they are easier to edit independently.

It's important that the object origins of the reference meshes and the collision meshes are in the same place. The easiest way to do this is select all the meshes, place the 3D cursor at the middle of the table, and press the "Centre cursor" button in the Mesh panel. This moves all the selected object's origins to the cursor. If we don't do this, the collision model and the visible model may not be aligned in-game, producing some weird effects.

We can export the SMD of the model (table.smd) by selecting the objects and using the export script as before. Make sure you only export to this file the meshes you want visible in-game.

To export the collision model we need to be a little careful. First we have to make sure that each convex part of the collision model is a separate object in Blender. In object mode, when you select the object (right-click), only that part should highlight. If two parts highlight from a single click, then they are in fact both in the same object. You can separate them by going into edit mode, selecting all vertices in one part of the object, and pressing the P key.

The model complier expects each part of a complex collision mesh to be in a separate smoothing group. Blender doesn't really have the concept of smoothing groups, but we can emulate it by selecting each object in the collision model one at a time, and hitting "Set Smooth". Don't select all the objects at once and hit "Set Smooth" - this will not produce the same result. Once we've done this, select all the collision objects and export them as table_phys.smd. Remember that the exporter script requires all meshes to be UV mapped, so apply a simple UV mapping to the collision meshes (it doesn't matter what texure you use or what it looks like, since it is never visible), before exporting.

As before, we need a table_idle.smd file to define the idle animation, which can be identical to the pcgmag_idle.smd file we used above.

Now we need a .qc file for the table prop:

$modelname table.mdl
$cdmaterials "models/rof"
$scale 12.0
$body studio "table.smd"
$sequence idle "table_idle" fps 1

$surfaceprop "Wood_Furniture"

$collisionmodel "table_phys.smd"
{
   $automass
   $concave
}

$keyvalues
{
   "prop_data"
   {
       "base"  "Wooden.Large"
   }
}

Note the differences from before. We've upped the scale a little, and set the $surfaceprop to "Wood_Furniture" and the prop data to "Wooden.Large" to reflect the type of prop we're making. In the $collisionmodel section, instead of the $mass command, we've used $automass. This makes the model compiler compute a mass for the object based on its size and material type. We could instead have explicitly specified the object's mass with the $mass command as before.

We've also added the $concave command to that section. This makes the compiler build a non-convex collision mesh for each part of the table_phys.smd file, rather than lump them all together in one convex shape. We can tell if this has worked when compiling the .qc file. The first lines of output from studiomdl.exe should look similar to this:

c:\steam\steamapps\username\half-life 2\hl2\modelsrc\, c:\steam\
steamapps\username\half-life 2\hl2\, path table
Working on "table.qc"
SMD MODEL table.smd
SMD MODEL table_idle.smd
SMD MODEL table_phys.smd
Model has 5 convex sub-parts
Collision model completed.
Computed Mass: 15.83 kg
...

Note the "model has 5 convex sub-parts" line, which means the collision model worked properly. If instead it read "Model has 1 convex sub-parts", we either didn't specify the $concave command, or failed to make the collision model meshes correctly.

Blender-table2.jpgBlender-table3.jpg

We can check the collision model by using the model viewer (hlmv.exe). On the "physics" tab, click the Highlight button and the collison mesh shows as a red wireframe. If we've got it right, it should look like the picture on the left: the wireframe follows each part individually. If we've got it wrong, it might look the picture on the right: the wireframe is a single shape wrapping the whole object. In game, the table model on the right would behave oddly - we couldn't shoot between the legs, and if knocked upside-down, object placed on it would hover on the invisible box covering the underside. The model on the left would behave as normal.

See also

For more information: First post on johnstoblog Second post on johnstoblog


See here for a message board discussion about an almost-complete Blender SMD export script with animation capabilities.

3D2Toy's SMD importer for Blender.