All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Deep Shadow/Camera Images

Table Of Contents

See Also
IMG3D: 3D Texture Images

Introduction To Deep Shadow/Camera Maps

A Deep Camera image is an image which stores values for each color channel at multiple depths for every pixel. A deep shadow image is a special case of a deep camera image which contains a single channel for opacity.

The HDK provides classes to read/write and evaluate Deep Camera Maps (and Deep Shadow Maps):

Reading A Deep Shadow/Camera Image

The IMG_DeepShadow class can be used in conjunction with the IMG_DeepPixelReader class to read raw pixel values from deep shadow images. See standalone/dsmprint.C for a simple example.

To evaluate a deep image at a given z-depth (with interpolation and filtering), please see TIL_TextureMap::deepLookup().

Creating A Deep Shadow/Camera Image

The example file standalone/i3ddsmgen.C reads a 3D texture file and converts it to a deep shadow image.

The writing process is fairly straight-forward:

// See IMG_DeepShadow::setOption()
fp.setOption("ofstorage", "real16");
fp.setOption("compression", "9");
fp.setOption("zbias", "0.05");
fp.addExtraChannel( IMG_DeepShadowChannel("Cf", Cf_Offset, 3) );
// Create the file
if (!fp.open("filename.dsm", xres, yres))
return false;
// Write pixels to file
for (y = 0; y < yres; y++)
for (x = 0; x < xres; x++)
writePixel(fp, x, y);
// Set texture options (these may be written before the pixels are
// written too).
UT_Options *opts = fp.getTBFOptions();
opts->setOptionM4("texture:identity_m4", UT_Matrix4(1));
opts->setOptionM4("texture:vector_123", UT_Vector3(1, 2, 3));
if (!fp.close())
return false;

When writing pixels, a single interleaved array of floats needs to be passed down for each z depth record. The first 3 floats of the buffer must be the opacity (red, green, blue) values for that depth. The buffer should have values for each extra channel referenced. For example:

writePixel(IMG_DeepShadow &fp, int x, int y)
float pixel_value[128];
if (!fp.pixelStart(x, y))
return false;
for (i = 0; i < nrecords; i++)
pixel_value[0] = opacity[i].r;
pixel_value[1] = opacity[i].g;
pixel_value[2] = opacity[i].b;
pixel_value[Cf_Offset+0] = color[i].r;
pixel_value[Cf_Offset+1] = color[i].g;
pixel_value[Cf_Offset+2] = color[i].b;
if (!fp.writePixel(zdepth[i], pixel_value, 128))
return false;
return fp.pixelClose();
If all the z-records are guaranteed to be in sorted order, then you calling IMG_DeepShadow::writePixelOrdered() will be more efficient.

When writing options for camera transforms, please see IMG_DeepShadow.h for details on the options expected.

DSM Camera Transforms

By default, mantra will store the information required to reconstruct the world-to-view and world-to-NDC transformation matrices in the TBFOptions stored on the map.

There are convenience functions (new in H12) which allow you to extract these matrices if they are available.

UT_Matrix4 xform;
dsm->getWorldToCamera(xform); // Extract the world-to-view transform
dsm->getCameraToNDC(xform); // The camera's projection matrix
dsm->getWorldToNDC(xform); // Extract the world-to-NDC transform

The world to NDC transform will return points in "homogeneous" space. To get the values in unit space (i.e. 0, 1), you will need to convert the point after transforming it.

UT_Matrix4 worldToNDC;
if (dsm->getWorldToNDC(worldToNDC))
UT_Vector3 P = worldP * worldToNDC;
// Remove homogeneous coordinates
P.x() = P.x()/P.w() * 0.5 + 0.5;
P.y() = P.y()/P.w() * 0.5 + 0.5;

To convert the z-coordinate, you will have to import the "camera:clip" option from the TBFOptions. This is a 2-tuple storing the near/far clipping planes.

This information may not always exist in the map. If it doesn't exist, the transform matrix will remain unchanged (i.e. uninitialized).