Click Here!
home account info subscribe login search My ITKnowledge FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Cutting Edge Direct 3D Programming
(Publisher: The Coriolis Group)
Author(s): Stan Trujillo
ISBN: 1576100502
Publication Date: 11/01/96

Bookmark It

Search this book:
 
Previous Table of Contents Next


Using Callback Functions

Early in this chapter, when we were using the Direct3D AppWizard to create the Sample application, we specified that we wanted an animated spotlight. The AppWizard added code to the project that updates the spotlight’s orientation during the execution of the program.

This updating is accomplished with a callback function. Callback functions are functions that Direct3D calls whenever it is about to perform a system update. These functions can be used to adjust program settings at runtime.

When we were creating the spotlight in the CreateScene() function, we installed a callback function named MoveLight(). The callback installation looks like this:

slightframe->AddMoveCallback( MoveLight, NULL );

The AddMoveCallback() function is a Direct3DRMFrame member function. The first argument is a pointer to the function that is to be called on each update. The second parameter is a pointer to data that will be passed to the callback function. This extra data is optional, so we are sending NULL.

The MoveLight() function adjusts the spotlight’s orientation. The code appears as follows:

void SampleWin::MoveLight(LPDIRECT3DRMFRAME lightframe, void*, D3DVALUE)
{
    // move the spotlight over the meshes
    static const D3DVALUE lim = D3DVALUE(0.3);
    static D3DVALUE xi = D3DVALUE(0.01);
    static D3DVALUE yi = D3DVALUE(0.005);
    static D3DVALUE x, y;
    if (x<-LIM || x>lim)
        xi=-xi;
    if (y<-LIM || y>lim)
        yi=-yi;
    x+=xi;
    y+=yi;
    lightframe->SetOrientation( NULL,
        x, y-1, D3DVALUE(1),
        D3DVALUE(0), D3DVALUE(1), D3DVALUE(0));
}

The function uses a simple “bouncing ball” algorithm to calculate a new orientation for the spotlight on each invocation. The spotlight’s movement is limited by the lim constant and is incremented with the xi and yi values. After a new orientation has been calculated, it is assigned to the frame with the SetOrientation() function.

Callback functions are always declared static, as shown:

class SampleWin : public RMWin
{
// ...
private:
    static void MoveLight(LPDIRECT3DRMFRAME frame, void* arg,
      D3DVALUE delta);
// ...
};

This is required, because regular member functions require an implicit class pointer. Declaring the function as static removes this dependency but means that the callback function cannot access the classes’ member functions. It is for this reason that the AddMoveCallback() function provides a way to supply the callback with extra data.

Callbacks installed with AddMoveCallback() are required to have three parameters. The first is a pointer to the frame interface that installed the callback. The second parameter is the pointer that is optionally used to supply extra data to the callback. The third parameter is the value that was passed to the Tick() function. Recall that the Tick() function can be used to slow and speed a program’s animation rate. If you always pass 1.0 to the Tick() function, then it is safe to ignore this parameter.

Shutting Things Down

Initializing Direct3D, creating scenes, and performing runtime animation is so much fun that it seems a shame to terminate a program, but it happens nevertheless.

The OnDestroy() Function

Before an MFC application terminates, the OnDestroy() function is called. This is a good place to release the references that we have created. RMWin provides a version of OnDestroy() that releases the standard Direct3D interfaces. The function looks like this:

void RMWin::OnDestroy()
{
    if (scene)
    {
        scene->Release();
        scene=0;

    }
    if (device)
    {
        device->Release();
        device=0;
    }

    if (d3drm)
    {
        d3drm->Release();
        d3drm=0;
    }

    if (clipper)
    {
        clipper->Release();
        clipper=0;
    }
}

Helper Functions

Some of the functions that we’ve looked at use functions that are not Win32, MFC, or Direct3D functions. These functions are convenience functions that the RMWin class provides. We’ll look at these functions next.

The ScaleMesh() Function

In the CreateScene() function, after the meshbuilder had been created and loaded, the ScaleMesh() function was used to insure that the mesh was a certain size. This code appears, again:

d3drm->CreateMeshBuilder( &meshbuilder );
r=meshbuilder->Load( meshname, NULL, D3DRMLOAD_FROMFILE, NULL, NULL );
if (r!=D3DRM_OK)
{
    CString msg;
    msg.Format( "Failed to load file '%s'\n", meshname );
    AfxMessageBox( msg );
    return FALSE;
}
ScaleMesh( meshbuilder, D3DVALUE(25) );

The ScaleMesh() function takes two arguments: a pointer to the meshbuilder and a size value. The size value is not a scale factor but rather an ideal size for the object. The ScaleMesh() function calculates a scale factor that will bring the largest dimension of the object as near as possible to the size limit. In the code above, ScaleMesh() scales the object so that its longest side is 25 units in length. The ScaleMesh() function looks like this:

void RMWin::ScaleMesh( LPDIRECT3DRMMESHBUILDER mesh, D3DVALUE dim)
{
    D3DRMBOX box;
    mesh->GetBox( &box );
    D3DVALUE sizex = box.max.x - box.min.x;
    D3DVALUE sizey = box.max.y - box.min.y;
    D3DVALUE sizez = box.max.z - box.min.z;
    D3DVALUE largedim=D3DVALUE(0);
    if (sizex>largedim)
        largedim=sizex;
    if (sizey>largedim)
        largedim=sizey;
    if (sizez>largedim)
        largedim=sizez;
    D3DVALUE scalefactor = dim/largedim;
    mesh->Scale( scalefactor, scalefactor, scalefactor );
}

The function uses the Direct3DRMMeshBuilder GetBox() function to retrieve the dimensions of the mesh. It uses this data to determine which dimension of the mesh is the longest and calculates a scale factor that will scale the object to the prescribed size. The last function call performs the scaling.

The GetMouse() Functions

The mouse is a fundamental part of Windows and users expect mouse support as much as they expect keyboard support. The GetMouseX() and GetMouseY() functions are supplied by the RMWin class so that your code can determine the current mouse location at any time. Both functions return the mouse position in pixel units. These functions are declared as static so that they can be used by callback functions.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited.