![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
Cutting Edge Direct 3D Programming
The MorphPlayWin::UpdateMorph() FunctionThe 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 FunctionsThe MorphPlay demo uses four functions to implement mesh rotation: OnLButtonDown(), OnLButtonUp(), UpdateDrag(), and OnIdle(). Lets 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 programs 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) ); } ConclusionIt 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:
Well, thats it for meshes. Weve taken a long look at vertex animation and use it in three demos. In Chapter 9, well study viewports inpossibly painfuldetail.
|
![]() |
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. |