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


The MorphPlayWin::UpdateMorph() Function

The morph sequence is controlled by the UpdateMorph() callback function:

void MorphPlayWin::UpdateMorph(LPDIRECT3DRMFRAME, void* ptr, D3DVALUE)
{
    MorphPlayWin* win=(MorphPlayWin*)ptr;
    const D3DVALUE maxtime=win->maxmorphtime;
    const int morphspeed=win->morphspeed;
    const D3DVALUE morphtimeinc=win->morphtimeinc;

    if (morphspeed==MORPH_FORWARD)
    {
        morphtime+=morphtimeinc;
        if (morphtime>maxtime)
            morphtime=D3DVALUE(0);
    }
    else if (morphspeed==MORPH_REVERSE)
    {
        morphtime-=morphtimeinc;
        if (morphtime<D3DVALUE(0))
            morphtime=maxtime;
    }
    else if (morphspeed==MORPH_BOTH)
    {
        static BOOL forward=TRUE;
        if (forward)
            morphtime+=morphtimeinc;
        else
            morphtime-=morphtimeinc;
        if (morphtime<D3DVALUE(0) || morphtime>maxtime)
            forward=1-forward;
    }

    win->SetMorphTime( morphtime );
}

A time is calculated for the morph sequence based on the morphspeed data member. If the morphspeed member is set to MORPH_FORWARD, the morph sequence time is incremented until it reaches the maximum time index. The value is then reset to zero. The morph time index is stored with the morphtime data member.

If the morphspeed data member is set to MORPH_REVERSE, the time value is calculated by subtracting values from the morphtime data member. The MORPH_BOTH constant causes the sequence to be played first forward, then in reverse.

Once the morphtime data member has been assigned, the MorphWin:: SetMorphTime() function is called. This call calculates the vertex data and updates the morph mesh.

The MorphPlayWin Mouse Functions

The MorphPlay demo uses four functions to implement mesh rotation: OnLButtonDown(), OnLButtonUp(), UpdateDrag(), and OnIdle(). Let’s look at the OnLButtonDown() function first:

void MorphPlayWin::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (!drag)
    {
        drag=TRUE;
        last_x = GetMouseX();
        last_y = GetMouseY();
        ShowCursor( FALSE );
        SetCapture();
    }
    MorphWin::OnLButtonDown(nFlags, point);
}

The function starts a new drag sequence if one is not already in progress. The drag data member is used to indicate the current drag status. If a new sequence is initiated, the current mouse position is stored, the mouse cursor is hidden, and the mouse capture mode is started with the MFC SetCapture() function. SetCapture() causes all mouse-related messages to be sent to the program’s window class, regardless of where on the screen the mouse is moved.

The OnLButtonUp() function looks like this:

void MorphPlayWin::OnLButtonUp(UINT nFlags, CPoint point)
{
    if (drag)
    {
        end_drag=TRUE;
        ReleaseCapture();
        ShowCursor( TRUE );
    }
    MorphWin::OnLButtonUp(nFlags, point);
}

The OnLButtonUp() function determines if a drag operation is in effect. If so, the end_drag data member is set to signal that the drag operation is to be terminated. Also, the mouse capture mode is terminated with the ReleaseCapture() function, and the mouse cursor is displayed.

The UpdateDrag() callback function is responsible for rotating the morph mesh during a drag operation. The code looks like this:

void MorphPlayWin::UpdateDrag(LPDIRECT3DRMFRAME frame, void*, D3DVALUE)
{
    if (drag)
    {
        double delta_x, delta_y;
        int x=GetMouseX();
        int y=GetMouseY();
        delta_x = x - last_x;
        delta_y = y - last_y;
        last_x = x;
        last_y = y;

        double delta_r = sqrt(delta_x * delta_x + delta_y * delta_y);
        double radius = 50;
        double denom;

        denom = sqrt(radius * radius + delta_r * delta_r);

        if (!(delta_r == 0 || denom == 0))
            frame->SetRotation( 0,
              D3DDivide(D3DVAL((float)-delta_y), D3DVAL((float)delta_r)),
              D3DDivide(D3DVAL((float)-delta_x), D3DVAL((float)delta_r)),
              D3DVAL(0.0),
              D3DDivide(D3DVAL((float)delta_r), D3DVAL((float)denom)));
    }

    if (end_drag)
    {
        drag=FALSE;
        end_drag=FALSE;
    }
}

The UpdateDrag() function converts the two dimensional mouse movement data (stored in the x, y, last_x, and last_y variables) to calculate a rotational vector for the mesh. The new rotation attribute is assigned with the Direct3DRMFrame SetRotation() function.

Finally, the OnIdle() function is used to prevent excessive mesh movement during drag operations:

void MorphPlayWin::OnIdle(LONG)
{
    if (drag && frame)
        frame->SetRotation( 0,
                D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0) );
}

Conclusion

It would probably be derelict of me to close this chapter without saying any more about how to create morph targets of your own. So, without getting into the details, here are a few suggestions:

  The easiest way to create compatible mesh targets is to create multiple instances of a single mesh and modify each instance. This is typically true regardless of what modeller you are using.
  The meshes in the scene do not have to be linked in a hierarchy. Naming them with single lowercase letters starting with ‘a’ will suffice.
  It is sometimes useful to use the “ignore frame transformation” options when converting 3DS files to X files using the DirectX CONV3DS utility.

Well, that’s it for meshes. We’ve taken a long look at vertex animation and use it in three demos. In Chapter 9, we’ll study viewports in—possibly painful—detail.


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.