DXA.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:7k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File:       dxa.cpp
  6.  *
  7.  *  This file contains functions that make use of DirectX Animation
  8.  *  to render animation to a ddraw surface.
  9.  *
  10.  ***************************************************************************/
  11. #include "dxa.h"
  12. IDAViewPtr DXA::_view = NULL;
  13. /*
  14.  * StartOle
  15.  *
  16.  * Start the Ole services.
  17.  */
  18. struct StartOle {
  19.     StartOle() { CoInitialize( NULL ); }
  20.     ~StartOle() { CoUninitialize(); }
  21. } _inst_StartOle;
  22. /*
  23.  * dump_com_error
  24.  *
  25.  * Dump the com error should an exception occurs in InitDXAViewObj.
  26.  * This is mainly for debugging purpose.
  27.  */
  28. void dump_com_error( _com_error &e )
  29. {
  30.     char buf[2048];
  31.     sprintf(buf, _T( "Oops - hit an error!ntCode = %08lxntCode meaning = %sn" ),
  32.             e.Error(), e.ErrorMessage());
  33.     OutputDebugString(buf);
  34. }
  35. /*
  36.  * initDXAViewObj
  37.  *
  38.  * Create the DAView object, construct the model, then start the model.
  39.  *
  40.  */
  41. BOOL DXA::initDXAViewObj(IUnknown *ddsurf)
  42. {
  43.     try {
  44.         IDAStaticsPtr e;
  45.         // Create the statics object
  46.         e.CreateInstance( L"DirectAnimation.DAStatics" );
  47.         
  48.         // Create and establish the view
  49.         _view.CreateInstance( L"DirectAnimation.DAView" );
  50.         // Import Media (images in this case).  The
  51. // GetCurrentDirectory() (which will return the path to either 
  52. // the debug or release sub directory) is used as a starting
  53. // point for relative file importing.
  54.         TCHAR szMediaBase[_MAX_PATH];
  55. TCHAR szImg[_MAX_PATH];
  56. TCHAR szHead[_MAX_PATH];
  57. // TCHAR szTest[_MAX_PATH];
  58.         
  59.         GetCurrentDirectory(sizeof(szMediaBase),szMediaBase);
  60. _tcscat(szMediaBase,_T("\..\..\..\..\..\media\"));
  61. _tcscpy(szImg,szMediaBase);
  62. _tcscat(szImg,_T("image\"));
  63. _tcscpy(szHead,szImg);
  64. _tcscat(szHead,_T("shingle.jpg"));
  65. // _tcscat(szTest,_T("shingle.jpg"));
  66.         
  67.         _bstr_t headPath = _bstr_t( szHead );
  68.     //    _bstr_t testPath = _bstr_t( szTest );
  69. IDAImagePtr head = e->ImportImage( headPath );
  70. //IDAImagePtr test = e->ImportImage( testPath );
  71.         
  72.         // Construct a new image by overlaying atop an empty image that
  73.         // has an infinite bounding box.  This allows subsequent crops
  74.         // to retain the "see-through-ness" that we're trying to
  75.         // achieve. 
  76.         head = e->Overlay( head, e->DetectableEmptyImage );
  77. // Construct four time varying values representing a rectangle
  78.         // whose position is changing, and whose size is changing.  x,
  79.         // y, width, and height.
  80.         IDANumberPtr xPos = myRange(-0.03,0.01,0.8,e);
  81.         IDANumberPtr yPos = myRange(-0.03,0.01,0.4,e);
  82.         IDANumberPtr width = myRange(0.01,0.07,1.5,e);
  83.         IDANumberPtr height = myRange(0.01,0.07,1.5,e);
  84.         // Combine these numbers into points at the corners of a
  85.         // rectangle. 
  86.         IDAPoint2Ptr hMin = e->Point2Anim( xPos, yPos );
  87.         IDAPoint2Ptr hMax =
  88.             e->Point2Anim( e->Add( xPos, width ), e->Add( yPos, height ) );
  89.         
  90.         // Apply this rectangle as the cropping rectangle
  91.         IDAImagePtr croppedHead = head->Crop( hMin, hMax );
  92.         
  93.         // Infinitely tile the result.  
  94.         IDAImagePtr headTiles = croppedHead->Tile();
  95.         
  96.         // Build up a time-varying transform...
  97.         IDATransform2Ptr xf1 = e->Translate2Anim( e->Mul( e->DANumber( 0.03 ),
  98.             e->Sin( e->LocalTime ) ), e->Mul( e->DANumber( 0.03 ),
  99.             e->Cos( e->Mul( e->LocalTime, e->DANumber( 0.3 ) ) ) ) );
  100.         
  101.         // ... and apply it to the head tiles to move the whole tiling
  102.         // around.   This completes our top image.
  103.         IDAImagePtr topIm = headTiles->Transform( xf1 );
  104.         
  105.         
  106.         ////// Bottom Image
  107.         
  108.         // build up a time-varying transform to apply to the bottom image.
  109.         IDATransform2Ptr xf2 = e->Translate2Anim( e->Mul( e->DANumber( 0.01 ),
  110.             e->Sin( e->LocalTime ) ), e->Mul( e->DANumber( 0.01 ),
  111.             e->Cos( e->LocalTime ) ) );
  112.         
  113.         // Construct two time varying colors that cycle through the
  114.         // hues. 
  115.         IDAColorPtr col1 = e->ColorHslAnim( e->Mul( e->LocalTime,
  116.             e->DANumber( 0.5 ) ), e->DANumber( 0.5 ), e->DANumber( 0.5 ) );
  117.         
  118.         IDAColorPtr col2 = e->ColorHslAnim( e->Mul( e->LocalTime,
  119.             e->DANumber( 0.43 ) ), e->DANumber( 0.5 ), e->DANumber( 0.5 ) );
  120.         
  121.         // Use these to construct a unit-sized gradient image with black
  122.         // and white at two corners, and these time-varying colors at
  123.         // the other two corners.
  124.         IDAImagePtr gradImg = e->GradientSquare( col1, e->Black,
  125.             col2, e->White );
  126.         
  127.         // Now scale this way down.
  128.         gradImg = gradImg->Transform( e->Scale2UniformAnim( e->DANumber( 0.065 ) ) );
  129.         
  130.         // Create the bottom image by transforming the gradient image
  131.         // around. 
  132.         IDAImagePtr botImg = gradImg->Transform( xf2 );
  133.         
  134.         ////// Entire model
  135.         
  136.         // Finally, overlay the top over the bottom over a solid white
  137.         // image. 
  138.         IDAImagePtr model = e->Overlay( topIm, e->Overlay( botImg, 
  139.       e->SolidColorImage( e->White ) ) );
  140.         
  141.         // Set the size of the viewport.  Not doing this  (as done in this
  142. // case) will render the animation accross the entire primary surface.
  143. _view->SetViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  144. // Let the view draw to the primary surface.
  145.         _view->IDirectDrawSurface = ddsurf;
  146. _view->CompositeDirectlyToTarget = FALSE;
  147. // Start the model on the view.
  148.         _view->StartModel(model, e->Silence, 0);
  149.     } catch (_com_error &e) {
  150.         dump_com_error( e );
  151.         return false;
  152.     }
  153.     return true;
  154. }
  155. /* myRange
  156.  * For constructing a time-varying range.  This function
  157.  * generates a time varying number bvr provided min and max
  158.  * values, and a rate (number of cycles per second).
  159.  */
  160. IDANumberPtr DXA::myRange( double min, double max, 
  161.   double rate, IDAStaticsPtr e )  {
  162.     // a = ( 1 + sin( time * rate ) ) * 0.5
  163.     IDANumberPtr a = e->Mul( e->Add( e->DANumber( 1 ),
  164.         e->Sin( e->Mul( e->DANumber( rate ), e->LocalTime ) ) ),
  165.         e->DANumber( 0.5 ) );
  166.     // b = (max - min) * a + min
  167.     IDANumberPtr b = e->Add( e->Mul( e->DANumber( max - min ), a ),
  168.         e->DANumber( min ) );
  169.     return b;
  170. }
  171. BOOL DXA::resetDXASurfaces(IUnknown *ddsurf)
  172. {
  173.     try {
  174.         _view->IDirectDrawSurface = ddsurf;
  175.     } catch (_com_error &e) {
  176.         dump_com_error( e );
  177.         return false;
  178.     }
  179.     return true;
  180. }
  181. /*
  182.  * tick
  183.  * Ask DA to sample and display the model.
  184.  */
  185. void DXA::tick() {
  186. static double startTime = 0;
  187.     struct _timeb timebuffer;
  188.     if (_view != NULL) {
  189.         _ftime( &timebuffer );
  190.         double thisTime = timebuffer.time + ( timebuffer.millitm / 1000.0 );
  191.         if ( startTime == 0 )  {
  192.             startTime = thisTime;
  193.             thisTime = 0;
  194.         }
  195.         else
  196.             thisTime -= startTime;
  197.         _view->Tick(thisTime);
  198.         _view->Render();
  199.     }
  200. }