Categories

Meta

Month: April 2010

“Dolly zoom” is a cinematography term for a method you’ll instantly recognise. Originally pioneered by Irmin Roberts, a Paramount Pictures cameraman, the method was made famous by its memorable use by Alfred Hitchcock for the film Vertigo. The cinema device has made numerous appearances since and is usually used for giving a sense of vertigo, unease or depicting the emotional impact of a realisation on a character. The basic premise is to keep the subject of the frame at the same scale while changing the scale of the background and/or foreground. This effect can be extremely good at giving a sense of vertigo and unreality.

Dolly zooming can be achieved by changing the field of view while changing the distance from the subject to ensure the subject remains approximately the same desired scale. When using an actual camera, this would be achieved by using a zoom lens (zoom lenses change the focal length and thus field of view) and at the same time physically moving backwards of forwards as appropriate.

Because of the non-linear relationship between the field of view and camera distance required to achieve this effect, it takes a good degree of experience and skill to do manually. In computer graphics, however we can use an equation to help us out. A common equation to achieve this effect is:

Now looking at the equation above, there are three variables. The field of view, which we can control and is therefore an input. The distance, which is calculated by the equation and is therefore the output. And finally, width which is a value relating to the target of our dolly zoom, this we will need to calculate ourselves. Fortunately this is straightforward as all we need do is multiply the target distance by the arctan of 90 degrees.

Assuming your camera view matrix is created using the standard Matrix.CreateLookAt() method, all you need adjust here is the camera eye position parameter. And assuming that the camera projection matrix is created using Matrix.CreatePerspectiveFieldOfView(), you can simply supply the field of view of the camera in radians.

In the development of many computer games, it is often important and necessary to store positions and meta data relating to 3d models and scenes. For example, you may have a model of a car and wish to place a number of meta-points on the model. Such as a point on the exhaust for a smoke emitter, points on the front for the headlights to project from, an object attachment point for that roof mounted turret, local damage helpers and positions inside the car for players to sit and interact with the steering wheel, to name but a few implementations. Rockstar North for example use this system in GTA: San Andreas by setting up dummies in 3d models. An example can be viewed here of a car from the game.

A method to address such a need is in placing pre-identified (essentially meta) bones throughout the model. There are many names for creatable objects in graphics packages which will export to bones, 3ds max has dummies, Maya has locators and most other software packages call them nulls (such as Lightwave, Softimage, Houdini, Blender and Cinema4d), systems like Unreal Engine call them pawns. These bones are connected to no geometry, which means its very easy to access them from your bone tree but they won’t visibly be displayed (unless you want them to be) and so are ideal for representing invisible helper points.

Some key uses of meta bones include:

Object attachment points, e.g. customisable weapon hard-points on a spaceship, or an articulated trailer on the back of a truck.

Particle emitter locations

Spawn points

Lights

Waypoints

CTF Locations

Weapon Pickups

King of the hill zones

Anchor points

How to make them

These objects are very easy to create in most packages, for example in 3ds max simply go to the create tab, then the helper tab and click the “Dummy” button and create the object in one of your viewports. You can accomplish the same in Maya by creating a locator, in Lightwave by creating a dummy and most other graphics packages use the term “null”.

Now that you’ve created one of these object, you now need to encode information about its purpose and relevance, which can be parsed by your game. In this article I describe storing the data and identification by encoding it into the bone name, however in the “Taking it further” section I cover some options for extending the capabilities of this meta-data. Each object should have a name which can identify every piece of information it needs to communicate to the game, such as the type of meta-object it is and some related data. Also note that bone names must be unique, so you may need to include some sort of unique identification number. As an example, you could approach encoding a smoke emitter like so: <type>-<subType>-<uniqueId>-<size> such as “emitter-smoke-01-50”. Bear in mind that there will be a comparatively small limit on the length of the name.

Also remember that it can get confusing having a lot of these objects in a scene, so confusing object a that does x with object b that does y is a problem. You may consider picking different colours for different types of objects.

How to load them and display them

Once exported, your nulls (or equivalent) should now be stored as model bones. You can retrieve a list of the model’s bones by accessing the collection of ModelBones, for example: myModel.Bones. You will then have a list of bones which store the name and world matrix, which is great as you can retrieve the relevant meta-tags stored in the name and decompose the world matrix into its translation and scale vector3s and a quaternion for rotation (you can convert this to your conventional Euler angles (i.e. yaw, pitch, roll) by using skytigercube’s method in this article at Creators Club.) For example:

1

2

3

4

Vector3 scale,translation,eulerRotation;

Quaternion rotation;

bone.Decompose(out scale,out rotation,out translation);

eulerRotation=QuaternionToYawPitchRoll(rotation);

You may wish to parse the bones in the model when you load the model in and build up the data structures which will rely on the stored meta-data. A quick example, which just runs through bones each Draw call and displays a sphere at all bones that begin with “myNamedTag” follows:

1

2

3

4

5

6

7

<em>foreach(ModelBone bone inmodel.Bones)

{

if(bone.Name.StartsWith(“myNamedTag”)

{

spherePrimitive.Draw(bone,view,projection,Color.White);

}

}</em>

Here any bones that begin with “myNamedTag” such as “myNamedTag01”, “myNamedTag02” and “myNamedTag-Front” will have a sphere drawn using their bone world matrix. Note that this is using the sphere primitive class from the Primitives3D Creators Club sample and relies upon an already sphere primitive.

Taking It Further

Encoding meta-data into the name of bones works fine for fairly simple implementations, however if an object has a lot of information attached to it this becomes less than ideal to encode everything into the contents of a small text box. You may consider encoding all this data into each object’s user defined properties (in 3ds max, other software will have equivalents.)

You could also make a custom tool to achieve more customised functionality or extend your graphics package’s functionality by taking into account its support for plugins and scripting (if it has the support) and coding in what you need.

And Finally

I hope this article has been informative. Criticism and comments are appreciated. If people want me to put together a quick sample I’ll be happy to do so, just comment.