home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / viewer / viewer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  57.1 KB  |  1,695 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: viewer.cpp
  6.  *
  7.  ***************************************************************************/
  8.  
  9. #define INITGUID
  10. #include "d3drmwin.h"
  11. #include "viewer.h"
  12.  
  13. #include <windows.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <malloc.h>
  17. #include <math.h>
  18. #include <direct.h>
  19. #include "sel.h"
  20.  
  21. static char ViewerClass[32] = "ViewerClass";
  22. static BOOL Render(void);
  23. HRESULT loadTextures(char *name, void *arg, LPDIRECT3DRMTEXTURE *tex);
  24.  
  25. typedef struct _AppInfo
  26. {
  27.     LPDIRECT3DRMFRAME scene, camera;
  28.     LPDIRECT3DRMDEVICE dev;
  29.     LPDIRECT3DRMVIEWPORT view;
  30.     D3DRMCOLORMODEL model;
  31.     BOOL bMinimized;
  32. } AppInfo;
  33.  
  34. AppInfo *active_window = NULL;
  35.  
  36. LPDIRECT3DRM lpD3DRM = 0;
  37. LPDIRECTDRAWCLIPPER lpDDClipper = 0;
  38. BOOL bQuit = FALSE;
  39.  
  40. static BOOL FirstInstance(HINSTANCE);
  41. static BOOL AnyInstance(HINSTANCE, int);
  42. long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM);
  43. static BOOL CreateDevice(HWND, AppInfo*);
  44. static void Idle();
  45. char* MyErrorToString(HRESULT error);
  46.  
  47. /* Msg
  48.  * Message output for error notification.
  49.  */
  50. void __cdecl
  51. Msg( LPSTR fmt, ... )
  52. {
  53.     char buff[256];
  54.  
  55.     wvsprintf(buff, fmt, (char *)(&fmt+1));
  56.     lstrcat(buff, "\r\n");
  57.     MessageBox( NULL, buff, "Viewer Message", MB_OK );
  58. }
  59.  
  60.  
  61. char* LSTRRCHR( const char* lpString, int bChar )
  62. {
  63.     if( lpString != NULL )
  64.     {
  65.         const char*     lpBegin;
  66.  
  67.         lpBegin = lpString;
  68.  
  69.         while( *lpString != 0 )
  70.         {
  71.             lpString++;
  72.         }
  73.  
  74.         while( 1 )
  75.         {
  76.             if( *lpString == bChar )
  77.             {
  78.                 return (char*)lpString;
  79.             }
  80.             
  81.             if( lpString == lpBegin )
  82.             {
  83.                 break;
  84.             }
  85.  
  86.             lpString--;
  87.         }
  88.     }
  89.  
  90.     return NULL;
  91. } /* LSTRRCHR */
  92.  
  93. /*
  94.  * Initialization, message loop
  95.  */
  96. int PASCAL WinMain
  97.     (HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline, int cmdshow)
  98. {
  99.     MSG         msg;
  100.     int         idle;
  101.     int         done = FALSE;
  102.     HACCEL      accel;
  103.     HRESULT     rval;
  104.  
  105.     prev_inst = prev_inst;
  106.     cmdline = cmdline;
  107.  
  108.     rval = Direct3DRMCreate(&lpD3DRM);
  109.     if (rval != D3DRM_OK) {
  110.         Msg("Failed to create Direct3DRM.\n%s", MyErrorToString(rval));
  111.         return 1;
  112.     }
  113.     if (!prev_inst)
  114.         if (!FirstInstance(this_inst))
  115.             return 1;
  116.  
  117.     if (!AnyInstance(this_inst, cmdshow))
  118.         return 1;
  119.     accel = LoadAccelerators(this_inst, "ViewerAccel");
  120.  
  121.     while (!done) {
  122.         idle = TRUE;
  123.         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  124.             idle = FALSE;
  125.             if (msg.message == WM_QUIT) {
  126.                 done = TRUE;
  127.                 break;
  128.             }
  129.             if (!TranslateAccelerator(msg.hwnd, accel, &msg)) {
  130.                 TranslateMessage(&msg);
  131.                 DispatchMessage(&msg);
  132.             }
  133.         }
  134.         if (!active_window->bMinimized && !bQuit)       {
  135.             if (idle) Idle();
  136.             if (!Render()) {
  137.                 Msg("Rendering failed.\n");
  138.                 done = TRUE;
  139.                 break;
  140.             }
  141.         }
  142.     }
  143.     RELEASE(active_window->scene);
  144.     RELEASE(active_window->camera);
  145.     RELEASE(active_window->view);
  146.     RELEASE(active_window->dev);
  147.     ClearClipboard();
  148.     RELEASE(lpD3DRM);
  149.     RELEASE(lpDDClipper);
  150.  
  151.     return msg.wParam;
  152. }
  153.  
  154. /*
  155.  * Register window class for the application, and do any other
  156.  * application initialization
  157.  */
  158. static BOOL FirstInstance(HINSTANCE this_inst)
  159. {
  160.     WNDCLASS    wc;
  161.     BOOL        rc;
  162.  
  163.     /*
  164.      * set up and register window class
  165.      */
  166.     wc.style = CS_HREDRAW | CS_VREDRAW;
  167.     wc.lpfnWndProc = WindowProc;
  168.     wc.cbClsExtra = 0;
  169.     wc.cbWndExtra = sizeof(DWORD);
  170.     wc.hInstance = this_inst;
  171.     wc.hIcon = LoadIcon(this_inst, "ViewerIcon");
  172.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  173.     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  174.     wc.lpszMenuName = "ViewerMenu";
  175.     wc.lpszClassName = ViewerClass;
  176.     rc = RegisterClass(&wc);
  177.  
  178.     return rc;
  179. }
  180.  
  181. /*
  182.  * Do work required for every instance of the application:
  183.  * create the window, initialize data
  184.  */
  185. static BOOL AnyInstance(HINSTANCE this_inst, int cmdshow)
  186. {
  187.     HWND win;
  188.     AppInfo *info;
  189.  
  190.     /*
  191.      * create main window
  192.      */
  193.     win =
  194.         CreateWindow
  195.         (   ViewerClass,                /* class */
  196.             "Direct3D Object Viewer",/* caption */
  197.             WS_OVERLAPPEDWINDOW,        /* style */
  198.             CW_USEDEFAULT,              /* init. x pos */
  199.             CW_USEDEFAULT,              /* init. y pos */
  200.             400,                        /* init. x size */
  201.             400,                        /* init. y size */
  202.             NULL,                       /* parent window */
  203.             NULL,                       /* menu handle */
  204.             this_inst,                  /* program handle */
  205.             NULL                        /* create parms */
  206.         );
  207.  
  208.  
  209.     if (!win) return FALSE;
  210.  
  211.     /*
  212.      * Create a clipper for this window
  213.      */
  214.     if (FAILED(DirectDrawCreateClipper(0, &lpDDClipper, NULL))) {
  215.         return FALSE;
  216.     }
  217.     if (FAILED(lpDDClipper->SetHWnd(0, win))) {
  218.         RELEASE(lpDDClipper);
  219.         return FALSE;
  220.     }
  221.     /*
  222.      * set up data associated with this window
  223.      */
  224.     info = (AppInfo*) malloc(sizeof(AppInfo));
  225.     SetWindowLong(win, 0, (long) info);
  226.     info->model = D3DCOLOR_MONO;
  227.     if (!CreateDevice(win, info)) {
  228.         return FALSE;
  229.     }
  230.  
  231.     /*
  232.      * display window
  233.      */
  234.     ShowWindow(win, cmdshow);
  235.     UpdateWindow(win);
  236.  
  237.     return TRUE;
  238. }
  239.  
  240. /*
  241.  * Processes messages for the about dialog.
  242.  */
  243. BOOL FAR PASCAL AboutDlgProc
  244.     (HWND win, unsigned msg, WORD wparam, LONG lparam)
  245. {
  246.     lparam = lparam;
  247.  
  248.     switch (msg)
  249.     {
  250.     case WM_INITDIALOG:
  251.         return TRUE;
  252.  
  253.     case WM_COMMAND:
  254.         if (wparam == IDOK)
  255.         {   EndDialog(win, TRUE);
  256.             return TRUE;
  257.         }
  258.         break;
  259.     }
  260.     return FALSE;
  261. }
  262.  
  263. /*
  264.  * Create a simple scene.
  265.  */
  266. static BOOL CreateScene(AppInfo* info)
  267. {
  268.     LPDIRECT3DRMFRAME frame = NULL;
  269.     LPDIRECT3DRMFRAME light = NULL;
  270.     LPDIRECT3DRMMESHBUILDER builder = NULL;
  271.     LPDIRECT3DRMLIGHT light1 = NULL;
  272.     LPDIRECT3DRMLIGHT light2 = NULL;
  273.     LPDIRECT3DRMMATERIAL mat = NULL;
  274.     HRESULT rval;
  275.  
  276.     if (FAILED(lpD3DRM->CreateFrame(NULL, &info->scene)))
  277.         goto generic_error;
  278.     if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVAL(1.0), D3DVAL(1.0), D3DVAL(1.0), &light1)))
  279.         goto generic_error;
  280.     if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1), D3DVAL(0.1), D3DVAL(0.1), &light2)))
  281.         goto generic_error;
  282.  
  283.     if (FAILED(lpD3DRM->CreateFrame(info->scene, &light)))
  284.         goto generic_error;
  285.     if (FAILED(light->SetPosition(info->scene, D3DVAL(2.0), D3DVAL(2.0), D3DVAL(5.0))))
  286.         goto generic_error;
  287.     if (FAILED(light->SetOrientation(info->scene, D3DVAL(-1.0), D3DVAL(-1.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0))))
  288.         goto generic_error;
  289.     if (FAILED(light->AddLight(light1)))
  290.         goto generic_error;
  291.     RELEASE(light1);
  292.     if (FAILED(info->scene->AddLight(light2)))
  293.         goto generic_error;
  294.     RELEASE(light2);
  295.     if (FAILED(lpD3DRM->CreateMeshBuilder(&builder)))
  296.         goto generic_error;
  297.     rval = builder->Load("camera.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL);
  298.     if (rval != D3DRM_OK) {
  299.         Msg("Failed to load camera.x.\n%s", MyErrorToString(rval));
  300.         goto ret_with_error;
  301.     }
  302.     if (FAILED(builder->SetQuality(D3DRMRENDER_UNLITFLAT)))
  303.         goto generic_error;
  304.     if (FAILED(light->AddVisual(builder)))
  305.         goto generic_error;
  306.     RELEASE(builder);
  307.     RELEASE(light);
  308.  
  309.     if (FAILED(lpD3DRM->CreateFrame(info->scene, &frame)))
  310.         goto generic_error;
  311.     if (FAILED(frame->SetRotation(info->scene, D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(-0.02))))
  312.         goto generic_error;
  313.     if (FAILED(frame->SetPosition(info->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(10.0))))
  314.         goto generic_error;
  315.     if (FAILED(lpD3DRM->CreateMeshBuilder(&builder)))
  316.         goto generic_error;
  317.     rval = builder->Load("mslogo.x", NULL, D3DRMLOAD_FROMFILE,
  318.         loadTextures, NULL);
  319.     if (rval != D3DRM_OK) {
  320.         Msg("Failed to load mslogo.x.\n%s", MyErrorToString(rval));
  321.         goto ret_with_error;
  322.     }
  323.     if (FAILED(builder->SetColorRGB(D3DVAL(0.8), D3DVAL(0.8), D3DVAL(0.8))))
  324.         goto generic_error;
  325.     if (FAILED(lpD3DRM->CreateMaterial(D3DVAL(10.0), &mat)))
  326.         goto generic_error;
  327.     if (FAILED(builder->SetMaterial(mat)))
  328.         goto generic_error;
  329.  
  330.     RELEASE(mat);
  331.     if (FAILED(frame->AddVisual(builder)))
  332.         goto generic_error;
  333.     RELEASE(builder);
  334.     RELEASE(frame);
  335.  
  336.     if (FAILED(lpD3DRM->CreateFrame(info->scene, &info->camera)))
  337.         goto generic_error;
  338.     if (FAILED(info->camera->SetPosition(info->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0))))
  339.         goto generic_error;
  340.     return TRUE;
  341. generic_error:
  342.     Msg("A failure occurred while creating the scene.\n");
  343. ret_with_error:
  344.     RELEASE(frame);
  345.     RELEASE(light);
  346.     RELEASE(builder);
  347.     RELEASE(light1);
  348.     RELEASE(light2);
  349.     RELEASE(mat);
  350.     return FALSE;
  351. }
  352.  
  353. static DWORD bppToddbd(int bpp)
  354. {
  355.     switch(bpp) {
  356.     case 1:
  357.         return DDBD_1;
  358.     case 2:
  359.         return DDBD_2;
  360.     case 4:
  361.         return DDBD_4;
  362.     case 8:
  363.         return DDBD_8;
  364.     case 16:
  365.         return DDBD_16;
  366.     case 24:
  367.         return DDBD_24;
  368.     case 32:
  369.         return DDBD_32;
  370.     }
  371.     return 0;
  372. }
  373.  
  374.  
  375. /*
  376.  * Find a device, preferably hardware, for a particular color model.
  377.  */
  378. LPGUID
  379. FindDevice(D3DCOLORMODEL cm)
  380. {
  381.     LPDIRECTDRAW lpDD;
  382.     LPDIRECT3D lpD3D;
  383.     D3DFINDDEVICESEARCH search;
  384.     static D3DFINDDEVICERESULT result;
  385.     HRESULT error;
  386.     HDC hdc;
  387.     int bpp;
  388.  
  389.     hdc = GetDC(NULL);
  390.     bpp = GetDeviceCaps(hdc, BITSPIXEL);
  391.     ReleaseDC(NULL, hdc);
  392.  
  393.     if (DirectDrawCreate(NULL, &lpDD, NULL))
  394.         return NULL;
  395.  
  396.     if (lpDD->QueryInterface(IID_IDirect3D, (void**) &lpD3D)) {
  397.         lpDD->Release();
  398.         return NULL;
  399.     }
  400.     
  401.     memset(&search, 0, sizeof search);
  402.     search.dwSize = sizeof search;
  403.     search.dwFlags = D3DFDS_COLORMODEL;
  404.     search.dcmColorModel = (cm == D3DCOLOR_MONO) ? D3DCOLOR_MONO : D3DCOLOR_RGB;
  405.  
  406.     memset(&result, 0, sizeof result);
  407.     result.dwSize = sizeof result;
  408.  
  409.     error = lpD3D->FindDevice(&search, &result);
  410.  
  411.     if (error == DD_OK) {
  412.         /*
  413.          * If the device found is hardware but cannot support the current
  414.          * bit depth, then fall back to software rendering.
  415.          */
  416.         if (result.ddHwDesc.dwFlags
  417.             && !(result.ddHwDesc.dwDeviceRenderBitDepth & bppToddbd(bpp))) {
  418.             
  419.             search.dwFlags |= D3DFDS_HARDWARE;
  420.             search.bHardware = FALSE;
  421.             memset(&result, 0, sizeof result);
  422.             result.dwSize = sizeof result;
  423.             error = lpD3D->FindDevice(&search, &result);
  424.         }
  425.     }
  426.  
  427.     lpD3D->Release();
  428.     lpDD->Release();
  429.  
  430.     if (error)
  431.         return NULL;
  432.     else
  433.         return &result.guid;
  434. }
  435.  
  436. /*
  437.  * Create the device and viewport.
  438.  */
  439. static BOOL CreateDevice(HWND win, AppInfo* info)
  440. {
  441.     RECT r;
  442.     int bpp;
  443.     HDC hdc;
  444.  
  445.     GetClientRect(win, &r);
  446.     if (FAILED(lpD3DRM->CreateDeviceFromClipper(lpDDClipper, FindDevice(info->model),
  447.                                 r.right, r.bottom, &info->dev)))
  448.                                 goto generic_error;
  449.     hdc = GetDC(win);
  450.     bpp = GetDeviceCaps(hdc, BITSPIXEL);
  451.     ReleaseDC(win, hdc);
  452.     switch (bpp)
  453.     {
  454.     case 1:
  455.         if (FAILED(info->dev->SetShades(4)))
  456.             goto generic_error;
  457.         if (FAILED(lpD3DRM->SetDefaultTextureShades(4)))
  458.             goto generic_error;
  459.         break;
  460.     case 16:
  461.         if (FAILED(info->dev->SetShades(32)))
  462.             goto generic_error;
  463.         if (FAILED(lpD3DRM->SetDefaultTextureColors(64)))
  464.             goto generic_error;
  465.         if (FAILED(lpD3DRM->SetDefaultTextureShades(32)))
  466.             goto generic_error;
  467.         if (FAILED(info->dev->SetDither(FALSE)))
  468.             goto generic_error;
  469.         break;
  470.     case 24:
  471.     case 32:
  472.         if (FAILED(info->dev->SetShades(256)))
  473.             goto generic_error;
  474.         if (FAILED(lpD3DRM->SetDefaultTextureColors(64)))
  475.             goto generic_error;
  476.         if (FAILED(lpD3DRM->SetDefaultTextureShades(256)))
  477.             goto generic_error;
  478.         if (FAILED(info->dev->SetDither(FALSE)))
  479.             goto generic_error;
  480.         break;
  481.     default:
  482.         if (FAILED(info->dev->SetDither(FALSE)))
  483.             goto generic_error;
  484.     }
  485.     if (!CreateScene(info))
  486.         goto ret_with_error;
  487.     if (FAILED(lpD3DRM->CreateViewport(info->dev, info->camera, 0, 0,
  488.         info->dev->GetWidth(),
  489.         info->dev->GetHeight(), &info->view)))
  490.         goto generic_error;
  491.     if (FAILED(info->view->SetBack(D3DVAL(5000.0))))
  492.         goto generic_error;
  493.  
  494.     return TRUE;
  495. generic_error:
  496.     Msg("An error occurred while creating the device.\n");
  497. ret_with_error:
  498.     return FALSE;
  499. }
  500.  
  501. /*
  502.  * Regenerate the device if the color model changes or the window size
  503.  * changes.
  504.  */
  505. static BOOL RebuildDevice(HWND win, AppInfo* info, int width, int height)
  506. {
  507.     HRESULT rval;
  508.     int old_dither = info->dev->GetDither();
  509.     D3DRMRENDERQUALITY old_quality = info->dev->GetQuality();
  510.     int old_shades = info->dev->GetShades();
  511.  
  512.     RELEASE(info->view);
  513.     RELEASE(info->dev);
  514.     rval = lpD3DRM->CreateDeviceFromClipper(lpDDClipper, FindDevice(info->model),
  515.                                 width, height, &info->dev);
  516.     if (rval != D3DRM_OK) {
  517.         Msg("Creating a device from HWND failed while rebuilding device.\n%s", MyErrorToString(rval));
  518.         return FALSE;
  519.     }
  520.  
  521.     if (FAILED(info->dev->SetDither(old_dither)))
  522.         goto generic_error;
  523.     if (FAILED(info->dev->SetQuality(old_quality)))
  524.         goto generic_error;
  525.     if (FAILED(info->dev->SetShades(old_shades)))
  526.         goto generic_error;
  527.     width = info->dev->GetWidth();
  528.     height = info->dev->GetHeight();
  529.     if (FAILED(lpD3DRM->CreateViewport(info->dev, info->camera,
  530.                           0, 0, width, height, &info->view)))
  531.                           goto generic_error;
  532.     if (FAILED(info->view->SetBack(D3DVAL(400.0))))
  533.         goto generic_error;
  534.     return TRUE;
  535. generic_error:
  536.     Msg("A failure occurred while rebuilding the device.\n");
  537.     return FALSE;
  538. }
  539.  
  540. /*
  541.  * Resize the viewport and device when the window size changes.
  542.  */
  543. static BOOL ResizeViewport(HWND win, AppInfo* info, int width, int height)
  544. {
  545.     int view_width = info->view->GetWidth();
  546.     int view_height = info->view->GetHeight();
  547.     int dev_width = info->dev->GetWidth();
  548.     int dev_height = info->dev->GetHeight();
  549.  
  550.     if (view_width == width && view_height == height)
  551.         return TRUE;
  552.     
  553.     if (width <= dev_width && height <= dev_height) {
  554.         RELEASE(info->view);
  555.         if (FAILED(lpD3DRM->CreateViewport(info->dev, info->camera, 0, 0, width, height, &info->view)))
  556.             goto generic_error;
  557.         if (FAILED(info->view->SetBack(D3DVAL(400.0))))
  558.             goto generic_error;
  559.     }
  560.  
  561.     if (!RebuildDevice(win, info, width, height))
  562.         return FALSE;
  563.     return TRUE;
  564. generic_error:
  565.     Msg("A failure occurred while resizing the viewport.\n");
  566.     return FALSE;
  567. }
  568.  
  569. /*
  570.  * Place an object in front of the camera.
  571.  */
  572. static BOOL PlaceMesh(LPDIRECT3DRMMESHBUILDER mesh, AppInfo *info)
  573. {
  574.     LPDIRECT3DRMFRAME frame;
  575.  
  576.     if (FAILED(lpD3DRM->CreateFrame(info->scene, &frame)))
  577.         return FALSE;
  578.     if (FAILED(frame->AddVisual(mesh)))
  579.         return FALSE;
  580.     if (FAILED(frame->SetPosition(info->camera, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(15.0))))
  581.         return FALSE;
  582.     frame->Release();
  583.     return TRUE;
  584. }
  585.  
  586. static BOOL ScaleScene(LPDIRECT3DRMFRAME frame, AppInfo *info)
  587. {
  588.   /* Some trickery form the RL2 viewer to scale a scene down to
  589.      managable proportions */
  590.   LPDIRECT3DRMMESHBUILDER mbuilder;
  591.   D3DRMBOX box;
  592.   D3DVALUE maxDim;
  593.  
  594.   lpD3DRM->CreateMeshBuilder(&mbuilder);
  595.   mbuilder->AddFrame(frame);
  596.   mbuilder->GetBox(&box);
  597.   mbuilder->Release();
  598.  
  599.   maxDim = box.max.x - box.min.x;
  600.   if (box.max.y - box.min.y > maxDim) 
  601.     maxDim = box.max.y - box.min.y;
  602.   if (box.max.z - box.min.z > maxDim)
  603.     maxDim = box.max.z - box.min.z;
  604.  
  605.   frame->AddScale(D3DRMCOMBINE_BEFORE, D3DDivide(D3DVAL(8.0), maxDim),
  606.                   D3DDivide(D3DVAL(8.0), maxDim),
  607.                   D3DDivide(D3DVAL(8.0), maxDim));
  608.  
  609.   frame->SetPosition(info->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(15.0));
  610.  
  611.   return TRUE;
  612. }
  613.                                                 
  614.  
  615. typedef struct {
  616.     LPDIRECT3DRMANIMATIONSET animset;
  617.     D3DVALUE time;
  618. } animationCallbackArgs;
  619.  
  620. static void animationCallback(LPDIRECT3DRMFRAME obj, void* arg, D3DVALUE delta)
  621. {
  622.     animationCallbackArgs* cb = (animationCallbackArgs *) arg;
  623.  
  624.     obj = obj;
  625.     cb->animset->SetTime(cb->time);
  626.     cb->time += delta;
  627. }
  628.  
  629. static BOOL setAnimationCallback(LPDIRECT3DRMFRAME frame, 
  630.                                  LPDIRECT3DRMANIMATIONSET animset)
  631. {
  632.     animationCallbackArgs *cb;
  633.  
  634.     cb = (animationCallbackArgs*)malloc(sizeof(animationCallbackArgs));
  635.     if (!cb)
  636.         return FALSE;
  637.  
  638.     cb->animset = animset;
  639.     cb->time = D3DVAL(0);
  640.     if (FAILED(frame->AddMoveCallback(animationCallback, (void *) cb)))
  641.         return FALSE;
  642.     return TRUE;
  643. }
  644.  
  645. static BOOL LoadAnimationSet(const char *filename, AppInfo *info)
  646. {
  647.   LPDIRECT3DRMANIMATIONSET lpAnimSet;
  648.   LPDIRECT3DRMFRAME lpFrame;
  649.  
  650.   /* Create a new parent frame for the animation, load it, and set up the
  651.      callback */
  652.   
  653.   if (FAILED(lpD3DRM->CreateFrame(info->scene, &lpFrame))) 
  654.     return FALSE;
  655.  
  656.   if (FAILED(lpD3DRM->CreateAnimationSet(&lpAnimSet))) 
  657.     return FALSE;
  658.  
  659.   if (FAILED(lpAnimSet->Load((LPVOID)filename, NULL, 
  660.                              D3DRMLOAD_FROMFILE, loadTextures,
  661.                              NULL, lpFrame)))
  662.     return FALSE;
  663.  
  664.   ScaleScene(lpFrame, info);
  665.  
  666.   setAnimationCallback(lpFrame, lpAnimSet);
  667.  
  668.   return TRUE;
  669. }
  670.   
  671. static BOOL LoadFrameHierarchy(const char *filename, AppInfo *info)
  672. {
  673.   LPDIRECT3DRMFRAME lpFrame;
  674.   
  675.   if (FAILED(lpD3DRM->CreateFrame(info->scene, &lpFrame)))
  676.     return FALSE;
  677.  
  678.   if (FAILED(lpFrame->Load((LPVOID)filename, NULL, D3DRMLOAD_FROMFILE,
  679.                            loadTextures, NULL)))
  680.     return FALSE;
  681.  
  682.   ScaleScene(lpFrame, info);
  683.  
  684.   return TRUE;
  685. }
  686.  
  687.  
  688. static int
  689.     left_drag = FALSE, right_drag = FALSE,
  690.     last_x, last_y;
  691.  
  692. /*
  693.  * Render the scene into the viewport.
  694.  */
  695. static BOOL Render() {
  696.     if (FAILED(active_window->scene->Move(D3DVAL(1.0))))
  697.         return FALSE;
  698.     if (FAILED(active_window->view->Clear()))
  699.         return FALSE;
  700.     if (FAILED(active_window->view->Render(active_window->scene)))
  701.         return FALSE;
  702.     if (FAILED(active_window->dev->Update()))
  703.         return FALSE;
  704.     return TRUE;
  705. }
  706.  
  707. static void Idle()
  708. {
  709.     LPDIRECT3DRMFRAME selected = SelectedFrame();
  710.  
  711.     if (active_window == NULL) return;
  712.     if (left_drag && selected)
  713.         selected->SetRotation(active_window->scene, D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0));
  714.     if (right_drag && selected)
  715.         selected->SetVelocity(active_window->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), FALSE);
  716. }
  717.  
  718. static int FillModeToMenuItem(D3DRMFILLMODE fm)
  719. {
  720.     switch (fm) {
  721.     case D3DRMFILL_POINTS:
  722.         return 2;
  723.  
  724.     case D3DRMFILL_WIREFRAME:
  725.         return 3;
  726.  
  727.     case D3DRMFILL_SOLID:
  728.         return 4;
  729.     }
  730.     return -1;
  731. }
  732.  
  733. static int ShadeModeToMenuItem(D3DRMSHADEMODE sm)
  734. {
  735.     switch (sm) {
  736.     case D3DRMSHADE_FLAT:
  737.         return 6;
  738.  
  739.     case D3DRMSHADE_GOURAUD:
  740.         return 7;
  741.  
  742.     case D3DRMSHADE_PHONG:
  743.         return 8;
  744.     }
  745.     return -1;
  746. }
  747.  
  748. static BOOL ToggleLighting(HWND win, AppInfo* info)
  749. {
  750.     HMENU menu;
  751.     D3DRMRENDERQUALITY quality = info->dev->GetQuality();
  752.     D3DRMLIGHTMODE mode = (D3DRMLIGHTMODE)(quality & D3DRMLIGHT_MASK);
  753.     HRESULT rval;
  754.  
  755.     if (mode == D3DRMLIGHT_ON)
  756.         mode = D3DRMLIGHT_OFF;
  757.     else
  758.         mode = D3DRMLIGHT_ON;
  759.  
  760.     menu = GetMenu(win);
  761.     menu = GetSubMenu(menu, 2);
  762.     CheckMenuItem(menu, 0, (MF_BYPOSITION
  763.                             | (mode == D3DRMLIGHT_ON
  764.                                ? MF_CHECKED
  765.                                : MF_UNCHECKED)));
  766.  
  767.     quality = (quality & ~D3DRMLIGHT_MASK) | mode;
  768.     rval = info->dev->SetQuality(quality);
  769.     if (rval != D3DRM_OK) {
  770.         Msg("Setting the render quality while toggling lighting failed.\n%s", MyErrorToString(rval));
  771.         return FALSE;
  772.     }
  773.     return TRUE;
  774. }
  775.  
  776. static BOOL SetFillMode(HWND win, AppInfo* info, D3DRMFILLMODE fm)
  777. {
  778.     HMENU menu;
  779.     D3DRMRENDERQUALITY quality = info->dev->GetQuality();
  780.     D3DRMFILLMODE oldfm = (D3DRMFILLMODE)(quality & D3DRMFILL_MASK);
  781.     HRESULT rval;
  782.  
  783.     menu = GetMenu(win);
  784.     menu = GetSubMenu(menu, 2);
  785.     CheckMenuItem(menu, FillModeToMenuItem(oldfm),
  786.                   MF_BYPOSITION|MF_UNCHECKED);
  787.     CheckMenuItem(menu, FillModeToMenuItem(fm),
  788.                   MF_BYPOSITION|MF_CHECKED);
  789.  
  790.     quality = (quality & ~D3DRMFILL_MASK) | fm;
  791.     rval = info->dev->SetQuality(quality);
  792.     if (rval != D3DRM_OK) {
  793.         Msg("Setting the render quality while changing the fill mode failed.\n%s", MyErrorToString(rval));
  794.         return FALSE;
  795.     }
  796.     return TRUE;
  797. }
  798.  
  799. static BOOL SetShadeMode(HWND win, AppInfo* info, D3DRMSHADEMODE sm)
  800. {
  801.     HMENU menu;
  802.     D3DRMRENDERQUALITY quality = info->dev->GetQuality();
  803.     D3DRMSHADEMODE oldsm = (D3DRMSHADEMODE)(quality & D3DRMSHADE_MASK);
  804.     HRESULT rval;
  805.  
  806.     menu = GetMenu(win);
  807.     menu = GetSubMenu(menu, 2);
  808.     CheckMenuItem(menu, ShadeModeToMenuItem(oldsm),
  809.                   MF_BYPOSITION|MF_UNCHECKED);
  810.     CheckMenuItem(menu, ShadeModeToMenuItem(sm),
  811.                   MF_BYPOSITION|MF_CHECKED);
  812.  
  813.     quality = (quality & ~D3DRMSHADE_MASK) | sm;
  814.     rval = info->dev->SetQuality(quality);
  815.     if (rval != D3DRM_OK) {
  816.         Msg("Setting the render quality while changing the shade mode failed.\n%s", MyErrorToString(rval));
  817.         return FALSE;
  818.     }
  819.     return TRUE;
  820. }
  821.  
  822. static BOOL SetModel(HWND win, AppInfo* info, D3DRMCOLORMODEL model)
  823. {
  824.     HMENU menu;
  825.     D3DRMCOLORMODEL oldModel = info->model;
  826.  
  827.     if (oldModel == model) return TRUE;
  828.  
  829.     info->model = model;
  830.     if (!RebuildDevice(win, info, info->dev->GetWidth(), info->dev->GetHeight()))
  831.         return FALSE;
  832.  
  833.     menu = GetMenu(win);
  834.     menu = GetSubMenu(menu, 2);
  835.     CheckMenuItem(menu, 9 + (int) oldModel, MF_BYPOSITION|MF_UNCHECKED);
  836.     CheckMenuItem(menu, 9 + (int) model, MF_BYPOSITION|MF_CHECKED);
  837.     return TRUE;
  838. }
  839.  
  840. static BOOL ToggleDither(HWND win, AppInfo *info)
  841. {
  842.     HMENU menu;
  843.     int dither = info->dev->GetDither();
  844.     int checked;
  845.     dither = !dither;
  846.     if (FAILED(info->dev->SetDither(dither))) {
  847.         Msg("Toggling dithering failed.\n");
  848.         return FALSE;
  849.     }
  850.     menu = GetMenu(win);
  851.     menu = GetSubMenu(menu, 2);
  852.  
  853.     if (dither) checked = MF_CHECKED;
  854.     else checked = MF_UNCHECKED;
  855.  
  856.     //CheckMenuItem(menu, MENU_DITHER, MF_BYCOMMAND|checked);
  857.     CheckMenuItem(menu, 13, MF_BYPOSITION|checked);
  858.     return TRUE;
  859. }
  860.  
  861. static BOOL ToggleTextureFiltering(HWND win, AppInfo *info)
  862. {
  863.     HMENU menu;
  864.     D3DRMTEXTUREQUALITY tq = info->dev->GetTextureQuality();
  865.     int checked;
  866.     if (tq == D3DRMTEXTURE_NEAREST)
  867.         tq = D3DRMTEXTURE_LINEAR;
  868.     else
  869.         tq = D3DRMTEXTURE_NEAREST;
  870.  
  871.     if (FAILED(info->dev->SetTextureQuality(tq))) {
  872.         Msg("Setting texture quality failed.\n");
  873.         return FALSE;
  874.     }
  875.     menu = GetMenu(win);
  876.     menu = GetSubMenu(menu, 2);
  877.  
  878.     if (tq == D3DRMTEXTURE_LINEAR) checked = MF_CHECKED;
  879.     else checked = MF_UNCHECKED;
  880.  
  881.     CheckMenuItem(menu, 14, MF_BYPOSITION|checked);
  882.     return TRUE;
  883. }
  884.  
  885. static BOOL
  886. CreateLight(WPARAM wparam, AppInfo* info)
  887. {
  888.     LPDIRECT3DRMMESHBUILDER builder = NULL;
  889.     LPDIRECT3DRMLIGHT light = NULL;
  890.     LPDIRECT3DRMFRAME frame = NULL;
  891.     HRESULT rval;
  892.  
  893.     if (FAILED(lpD3DRM->CreateMeshBuilder(&builder)))
  894.         goto generic_error;
  895.  
  896.     if (wparam == MENU_LIGHT_DIRECTIONAL) {
  897.         rval = builder->Load("camera.x", NULL, D3DRMLOAD_FROMFILE,
  898.                              NULL, NULL);
  899.         if (rval != D3DRM_OK) {
  900.             Msg("Failed to load camera.x.\n%s", MyErrorToString(rval));
  901.             goto ret_with_error;
  902.         }
  903.         if (FAILED(builder->SetQuality(D3DRMRENDER_UNLITFLAT)))
  904.             goto generic_error;
  905.         if (FAILED(lpD3DRM->CreateLightRGB
  906.             (D3DRMLIGHT_DIRECTIONAL, D3DVAL(1.0), D3DVAL(1.0), D3DVAL(1.0), &light)))
  907.             goto generic_error;
  908.     } else if (wparam == MENU_LIGHT_PARALLEL_POINT) {
  909.         rval = builder->Load("sphere2.x", NULL, D3DRMLOAD_FROMFILE,
  910.                              NULL, NULL);
  911.         if (rval != D3DRM_OK) {
  912.             Msg("Failed to load sphere2.x.\n%s", MyErrorToString(rval));
  913.             goto ret_with_error;
  914.         }
  915.         if (FAILED(builder->SetQuality(D3DRMRENDER_UNLITFLAT)))
  916.             goto generic_error;
  917.         if (FAILED(builder->Scale(D3DVAL(0.2), D3DVAL(0.2), D3DVAL(0.2))))
  918.             goto generic_error;
  919.         if (FAILED(lpD3DRM->CreateLightRGB
  920.             (D3DRMLIGHT_PARALLELPOINT, D3DVAL(1.0), D3DVAL(1.0), D3DVAL(1.0), &light)))
  921.             goto generic_error;
  922.     } else if (wparam == MENU_LIGHT_POINT) {
  923.         rval = builder->Load("sphere2.x", NULL, D3DRMLOAD_FROMFILE,
  924.                              NULL, NULL);
  925.         if (rval != D3DRM_OK) {
  926.             Msg("Failed to load sphere2.x.\n%s", MyErrorToString(rval));
  927.             goto ret_with_error;
  928.         }
  929.         if (FAILED(builder->SetQuality(D3DRMRENDER_UNLITFLAT)))
  930.             goto generic_error;
  931.         if (FAILED(builder->Scale(D3DVAL(0.2), D3DVAL(0.2), D3DVAL(0.2))))
  932.             goto generic_error;
  933.         if (FAILED(lpD3DRM->CreateLightRGB
  934.             (D3DRMLIGHT_POINT, D3DVAL(1.0), D3DVAL(1.0), D3DVAL(1.0), &light)))
  935.             goto generic_error;
  936.     } else if (wparam == MENU_LIGHT_SPOT) {
  937.         rval = builder->Load("camera.x", NULL, D3DRMLOAD_FROMFILE,
  938.                              NULL, NULL);
  939.         if (rval != D3DRM_OK) {
  940.             Msg("Failed to load camera.x.\n%s", MyErrorToString(rval));
  941.             goto ret_with_error;
  942.         }
  943.         if (FAILED(builder->SetQuality(D3DRMRENDER_UNLITFLAT)))
  944.             goto generic_error;
  945.         if (FAILED(lpD3DRM->CreateLightRGB(D3DRMLIGHT_SPOT, D3DVAL(1.0), D3DVAL(1.0), D3DVAL(1.0), &light)))
  946.             goto generic_error;
  947.     }
  948.     if (FAILED(lpD3DRM->CreateFrame(info->scene, &frame)))
  949.         goto generic_error;
  950.     if (FAILED(frame->SetPosition(info->camera, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(10.0))))
  951.         goto generic_error;
  952.     if (FAILED(frame->AddVisual(builder)))
  953.         goto generic_error;
  954.     if (FAILED(frame->AddLight(light)))
  955.         goto generic_error;
  956.  
  957.     builder->Release(), frame->Release(), light->Release();
  958.     return TRUE;
  959. generic_error:
  960.     Msg("A failure occurred while creating a new light.\n");
  961. ret_with_error:
  962.     RELEASE(builder);
  963.     RELEASE(light);
  964.     RELEASE(frame);
  965.     return FALSE;
  966. }
  967.  
  968. HRESULT loadTextures(char *name, void *arg, LPDIRECT3DRMTEXTURE *tex)
  969. {
  970.     char* ext = LSTRRCHR(name, (int)'.');
  971.  
  972.     if (ext && !lstrcmpi(ext, ".ppm"))
  973.         return lpD3DRM->LoadTexture(name, tex);
  974.     else return -1;
  975. }
  976.  
  977. #define SIGN_EXTEND(w)    ((((int)(w)) << 16) >> 16)
  978.  
  979. /*
  980.  * Handle messages for the main application window
  981.  */
  982. LONG FAR PASCAL WindowProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam)
  983. {
  984.     static HCURSOR oldCursor = NULL;
  985.     AppInfo *info;
  986.     LPDIRECT3DRMFRAME sFrame = SelectedFrame();
  987.     LPDIRECT3DRMMESHBUILDER sVisual = SelectedVisual();
  988.  
  989.     info = (AppInfo *) GetWindowLong(win, 0);
  990.     active_window = info;
  991.  
  992.     switch (msg)
  993.     {
  994.     case WM_KEYDOWN:
  995.         {   D3DVECTOR dir, up, right;
  996.  
  997.             info->camera->GetOrientation(info->scene, &dir, &up);
  998.             D3DRMVectorCrossProduct(&right, &up, &dir);
  999.             up.x /= D3DVAL(4.0);
  1000.             up.y /= D3DVAL(4.0);
  1001.             up.z /= D3DVAL(4.0);
  1002.             right.x /= D3DVAL(4.0);
  1003.             right.y /= D3DVAL(4.0);
  1004.             right.z /= D3DVAL(4.0);
  1005.  
  1006.             switch (wparam)
  1007.             {
  1008.             case 'T':
  1009.                 info->camera->SetVelocity(info->scene, dir.x, dir.y, dir.z, FALSE);
  1010.                 break;
  1011.  
  1012.             case 'Y':
  1013.                 info->camera->SetVelocity(info->scene, D3DVAL(-100.0) * dir.x,
  1014.                                           D3DVAL(-100.0) * dir.y, 
  1015.                                           D3DVAL(-100.0) * dir.z, FALSE);
  1016.  
  1017.             case 'R':
  1018.                 info->camera->SetVelocity(info->scene, -dir.x, -dir.y, -dir.z, FALSE);
  1019.                 break;
  1020.                  
  1021.             case 'E':
  1022.                 info->camera->SetVelocity(info->scene, D3DVAL(100.0) * dir.x,
  1023.                                           D3DVAL(100.0) * dir.y, 
  1024.                                           D3DVAL(100.0) * dir.z, FALSE);
  1025.             case VK_UP:
  1026.                 info->camera->SetVelocity(info->scene, up.x, up.y, up.z, FALSE);
  1027.                 break;
  1028.  
  1029.             case VK_DOWN:
  1030.                 info->camera->SetVelocity(info->scene, -up.x, -up.y, -up.z, FALSE);
  1031.                 break;
  1032.  
  1033.             case VK_RIGHT:
  1034.                 info->camera->SetVelocity(info->scene, right.x, right.y, right.z, FALSE);
  1035.                 break;
  1036.  
  1037.             case VK_LEFT:
  1038.                 info->camera->SetVelocity(info->scene, -right.x, -right.y, -right.z, FALSE);
  1039.                 break;
  1040.  
  1041.             case 'X':
  1042.                 if (sFrame)
  1043.                     sFrame->SetVelocity(info->scene, dir.x, dir.y, dir.z, FALSE);
  1044.                 break;
  1045.  
  1046.             case 'Z':
  1047.                 if (sFrame)
  1048.                     sFrame->SetVelocity(info->scene, -dir.x, -dir.y, -dir.z, FALSE);
  1049.                 break;
  1050.  
  1051.             case VK_SUBTRACT:
  1052.                 if (sFrame)
  1053.                 {   sVisual->Scale(D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9));
  1054.                     SelectVisual(sVisual, sFrame);
  1055.                 }
  1056.                 break;
  1057.  
  1058.             case VK_ADD:
  1059.                 if (sFrame)
  1060.                 {   sVisual->Scale(D3DVAL(1.1), D3DVAL(1.1), D3DVAL(1.1));
  1061.                     SelectVisual(sVisual, sFrame);
  1062.                 }
  1063.                 break;
  1064.             }
  1065.         }
  1066.         break;
  1067.  
  1068.     case WM_KEYUP:
  1069.         switch (wparam)
  1070.         {
  1071.         case 'T':
  1072.         case 'R':
  1073.         case VK_UP:
  1074.         case VK_DOWN:
  1075.         case VK_LEFT:
  1076.         case VK_RIGHT:
  1077.             info->camera->SetVelocity(info->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), FALSE);
  1078.             break;
  1079.  
  1080.         case 'Z':
  1081.         case 'X':
  1082.             if (sFrame)
  1083.                 sFrame->SetVelocity(info->scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), FALSE);
  1084.             break;
  1085.         }
  1086.         break;
  1087.  
  1088.     case WM_LBUTTONDOWN:
  1089.         {   HCURSOR hCur;
  1090.             int x = LOWORD(lparam);
  1091.             int y = HIWORD(lparam);
  1092.             last_x = x;
  1093.             last_y = y;
  1094.             FindAndSelectVisual(info->view, x, y);
  1095.             left_drag = TRUE;
  1096.             SetCapture(win);
  1097.             /* change to a groovy cursor */
  1098.             hCur = LoadCursor(NULL, IDC_ARROW);
  1099.             if (hCur) oldCursor = SetCursor(hCur);
  1100.             else oldCursor = NULL;
  1101.         }
  1102.         break;
  1103.  
  1104.     case WM_LBUTTONUP:
  1105.         ReleaseCapture();
  1106.         left_drag = FALSE;
  1107.         if (oldCursor) SetCursor(oldCursor);
  1108.         break;
  1109.  
  1110.     case WM_RBUTTONDOWN:
  1111.         {
  1112.             HCURSOR hCur;
  1113.             int x = LOWORD(lparam);
  1114.             int y = HIWORD(lparam);
  1115.             last_x = x;
  1116.             last_y = y;
  1117.             FindAndSelectVisual(info->view, x, y);
  1118.             right_drag = TRUE;
  1119.             SetCapture(win);
  1120.             /* change to a groovy cursor */
  1121.             hCur = LoadCursor(NULL, IDC_ARROW);
  1122.             if (hCur) oldCursor = SetCursor(hCur);
  1123.             else oldCursor = NULL;
  1124.         }
  1125.         break;
  1126.  
  1127.     case WM_RBUTTONUP:
  1128.         right_drag = FALSE;
  1129.         ReleaseCapture();
  1130.         if (oldCursor) SetCursor(oldCursor);
  1131.         break;
  1132.  
  1133.     case WM_MOUSEMOVE:
  1134.         if ((wparam & MK_LBUTTON) && sFrame && left_drag)
  1135.         {   double delta_x, delta_y;
  1136.             delta_x = SIGN_EXTEND(LOWORD(lparam)) - last_x;
  1137.             delta_y = -SIGN_EXTEND((HIWORD(lparam)) - last_y);
  1138.             last_x = SIGN_EXTEND(LOWORD(lparam));
  1139.             last_y = SIGN_EXTEND(HIWORD(lparam));
  1140.             {
  1141.                 double delta_r = sqrt(delta_x * delta_x + delta_y * delta_y);
  1142.                 double radius = 50;
  1143.                 double denom;
  1144.  
  1145.                 denom = sqrt(radius * radius + delta_r * delta_r);
  1146.  
  1147.                 if (delta_r == 0 || denom == 0) break;
  1148.                 sFrame->SetRotation
  1149.                 (   info->camera,
  1150.                     D3DDivide(D3DVAL((float) delta_y), D3DVAL((float) delta_r)),
  1151.                     D3DDivide(D3DVAL((float) -delta_x), D3DVAL((float) delta_r)),
  1152.                     D3DVAL(0.0),
  1153.                     D3DDivide(D3DVAL((float) delta_r), D3DVAL((float) denom))
  1154.                 );
  1155.             }
  1156.         }
  1157.         else if ((wparam & MK_RBUTTON) && sFrame && right_drag)
  1158.         {   double delta_x, delta_y;
  1159.             D3DVECTOR p1;
  1160.             D3DRMVECTOR4D p2;
  1161.  
  1162.             delta_x = SIGN_EXTEND(LOWORD(lparam)) - last_x;
  1163.             delta_y = SIGN_EXTEND(HIWORD(lparam)) - last_y;
  1164.             last_x = SIGN_EXTEND(LOWORD(lparam));
  1165.             last_y = SIGN_EXTEND(HIWORD(lparam));
  1166.             sFrame->GetPosition(info->scene, &p1);
  1167.             info->view->Transform(&p2, &p1);
  1168.             p2.x += D3DMultiply(D3DVAL((float)delta_x), p2.w);
  1169.             p2.y += D3DMultiply(D3DVAL((float)delta_y), p2.w);
  1170.             info->view->InverseTransform(&p1, &p2);
  1171.             sFrame->SetPosition(info->scene, p1.x, p1.y, p1.z);
  1172.         }
  1173.         break;
  1174.  
  1175.     case WM_COMMAND:
  1176.         switch( wparam & 0xffff )
  1177.         {
  1178.         case MENU_FILE_ABOUT:
  1179.             DialogBox((HINSTANCE) GetWindowLong(win, GWL_HINSTANCE),"AboutBox", win, (DLGPROC)AboutDlgProc);
  1180.             break;
  1181.  
  1182.         case MENU_FILE_OPEN:
  1183.           {  LPDIRECT3DRMMESHBUILDER builder;
  1184.              HRESULT rval;
  1185.              char *file = OpenNewFile(win, "Open a Mesh file");
  1186.              if (file)
  1187.                {
  1188.                  if (FAILED(lpD3DRM->CreateMeshBuilder(&builder))) {
  1189.                    Msg("Failed the create a builder for the new mesh.\n");
  1190.                    break;
  1191.                  }
  1192.                  rval = builder->Load(file, NULL, D3DRMLOAD_FROMFILE,
  1193.                                       loadTextures, NULL);
  1194.                  if (rval != D3DRM_OK) {
  1195.                    Msg("Loading %s failed.\n%s", file, MyErrorToString(rval));
  1196.                    builder->Release();
  1197.                    break;
  1198.                  }
  1199.                  if (!PlaceMesh(builder, info)) {
  1200.                    Msg("Placing the mesh in the scene failed.\n");
  1201.                    builder->Release();
  1202.                    break;
  1203.                  }
  1204.                  builder->Release();
  1205.                }
  1206.  
  1207.              /*LoadAnimationSet(file, info);*/
  1208.              break;
  1209.           }
  1210.  
  1211.         case MENU_FILE_OPEN_ANIMSET:
  1212.           {
  1213.             char *file = OpenNewFile(win, "Open Animation ...");
  1214.             if (file) {
  1215.               if (LoadAnimationSet(file, info) == FALSE) {
  1216.                 Msg("Loading and placing of %s failed.\n", file);
  1217.               }
  1218.             }
  1219.             break;
  1220.           }
  1221.  
  1222.         case MENU_FILE_OPEN_FRAME:
  1223.             {
  1224.               char *file = OpenNewFile(win, "Open Frame ...");
  1225.               if (file) {
  1226.                 if (LoadFrameHierarchy(file, info) == FALSE) {
  1227.                   Msg("Loading and placing of %s failed.\n", file);
  1228.                 }
  1229.               }
  1230.               break;
  1231.             }
  1232.  
  1233.         case MENU_FILE_EXIT:
  1234.             PostQuitMessage(0);
  1235.             break;
  1236.  
  1237.         case MENU_EDIT_CUT:
  1238.             CutVisual();
  1239.             break;
  1240.  
  1241.         case MENU_EDIT_COPY:
  1242.             CopyVisual();
  1243.             break;
  1244.  
  1245.         case MENU_EDIT_PASTE:
  1246.             PasteVisual(info->scene);
  1247.             break;
  1248.  
  1249.         case MENU_EDIT_DELETE:
  1250.             DeleteVisual();
  1251.             break;
  1252.  
  1253.         case MENU_EDIT_COLOR:
  1254.             if (sFrame)
  1255.             {
  1256.                 LPDIRECT3DRMMESHBUILDER mesh;
  1257.                 HRESULT rval;
  1258.  
  1259.                 if (FAILED(sVisual->QueryInterface(IID_IDirect3DRMMeshBuilder,
  1260.                                                    (void**) &mesh)))
  1261.                     break;
  1262.  
  1263.                 if (SelectedLight())
  1264.                 {
  1265.                     D3DCOLOR c = SelectedLight()->GetColor();
  1266.  
  1267.                     if (ChooseNewColor(win, &c)) {
  1268.                         mesh->SetColor(c);
  1269.                         SelectedLight()->SetColor(c);
  1270.                     }
  1271.                 } else {
  1272.                     D3DCOLOR c;
  1273.  
  1274.                     if (mesh->GetFaceCount()) {
  1275.                         LPDIRECT3DRMFACEARRAY faces;
  1276.                         LPDIRECT3DRMFACE face;
  1277.                         mesh->GetFaces(&faces);
  1278.                         faces->GetElement(0, &face);
  1279.                         c = face->GetColor();
  1280.                         RELEASE(face);
  1281.                         RELEASE(faces);
  1282.                     } else
  1283.                         c = D3DRMCreateColorRGB(D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0));
  1284.  
  1285.                     if (ChooseNewColor(win, &c)) {
  1286.                         rval = mesh->SetColor(c);
  1287.                         if (rval != D3DRM_OK)
  1288.                             Msg("Failed to set the mesh's color.\n%s", MyErrorToString(rval));
  1289.                     }
  1290.                 }
  1291.  
  1292.                 RELEASE(mesh);
  1293.             }
  1294.             break;
  1295.  
  1296.         case MENU_EDIT_BOXES:
  1297.             {
  1298.                 HMENU menu;
  1299.                 int checked = ToggleBoxes() ? MF_CHECKED : MF_UNCHECKED;
  1300.                 menu = GetMenu(win);
  1301.                 menu = GetSubMenu(menu, 1);
  1302.                 CheckMenuItem(menu, MENU_EDIT_BOXES, MF_BYCOMMAND|checked);
  1303.             }
  1304.             break;
  1305.  
  1306.         case MENU_QUALITY_LIGHTING:
  1307.             ToggleLighting(win, info);
  1308.             break;
  1309.  
  1310.         case MENU_QUALITY_POINTS:
  1311.             SetFillMode(win, info, D3DRMFILL_POINTS);
  1312.             break;
  1313.  
  1314.         case MENU_QUALITY_WIREFRAME:
  1315.             SetFillMode(win, info, D3DRMFILL_WIREFRAME);
  1316.             break;
  1317.  
  1318.         case MENU_QUALITY_SOLID:
  1319.             SetFillMode(win, info, D3DRMFILL_SOLID);
  1320.             break;
  1321.  
  1322.         case MENU_QUALITY_FLAT:
  1323.             SetShadeMode(win, info, D3DRMSHADE_FLAT);
  1324.             break;
  1325.  
  1326.         case MENU_QUALITY_GOURAUD:
  1327.             SetShadeMode(win, info, D3DRMSHADE_GOURAUD);
  1328.             break;
  1329.  
  1330.         case MENU_QUALITY_PHONG:
  1331.             SetShadeMode(win, info, D3DRMSHADE_PHONG);
  1332.             break;
  1333.  
  1334.         case MENU_MODEL_MONO:
  1335.             SetModel(win, info, D3DCOLOR_MONO);
  1336.             break;
  1337.  
  1338.         case MENU_MODEL_RGB:
  1339.             SetModel(win, info, D3DCOLOR_RGB);
  1340.             break;
  1341.  
  1342.         case MENU_DITHER:
  1343.             ToggleDither(win, info);
  1344.             break;
  1345.  
  1346.         case MENU_TEXTURE_FILTERING:
  1347.             ToggleTextureFiltering(win, info);
  1348.             break;
  1349.  
  1350.         case MENU_LIGHT_DIRECTIONAL:
  1351.         case MENU_LIGHT_PARALLEL_POINT:
  1352.         case MENU_LIGHT_POINT:
  1353.         case MENU_LIGHT_SPOT:
  1354.             {
  1355.                 CreateLight(wparam, info);
  1356.             }
  1357.             break;
  1358.         }
  1359.         break;
  1360.  
  1361.     case WM_DESTROY:
  1362.         PostQuitMessage( 0 );
  1363.         bQuit = TRUE;
  1364.         break;
  1365.  
  1366.     case WM_SIZE:
  1367.         {
  1368.             int width = LOWORD(lparam);
  1369.             int height = HIWORD(lparam);
  1370.                 if (width && height) {
  1371.                         if (!ResizeViewport(win, info, width, height)) {
  1372.                             bQuit = TRUE;
  1373.                             break;
  1374.                         }   
  1375.                         active_window->bMinimized = FALSE;
  1376.                 } else {
  1377.                         active_window->bMinimized = TRUE;
  1378.                 }
  1379.         }
  1380.         break;
  1381.  
  1382.     case WM_ACTIVATE:
  1383.         {   LPDIRECT3DRMWINDEVICE windev;
  1384.  
  1385.             if (SUCCEEDED(info->dev->QueryInterface(IID_IDirect3DRMWinDevice, (void **) &windev)))
  1386.             {   if (FAILED(windev->HandleActivate(wparam)))
  1387.                     Msg("Failed to handle WM_ACTIVATE.\n");
  1388.                 windev->Release();
  1389.             } else {
  1390.                 Msg("Failed to create Windows device to handle WM_ACTIVATE.\n");
  1391.             }
  1392.         }
  1393.         break;
  1394.  
  1395.     case WM_PAINT:
  1396.         if (info)
  1397.         {   RECT r;
  1398.             PAINTSTRUCT ps;
  1399.             LPDIRECT3DRMWINDEVICE windev;
  1400.  
  1401.             if (GetUpdateRect(win, &r, FALSE))
  1402.             {   BeginPaint(win, &ps);
  1403.                 if (SUCCEEDED(info->dev->QueryInterface(IID_IDirect3DRMWinDevice, (void **) &windev)))
  1404.                 {   if (FAILED(windev->HandlePaint(ps.hdc)))
  1405.                         Msg("Failed to handle WM_PAINT.\n");
  1406.                     windev->Release();
  1407.                 } else {
  1408.                     Msg("Failed to create Windows device to handle WM_PAINT.\n");
  1409.                 }
  1410.                 EndPaint(win, &ps);
  1411.             }
  1412.         }
  1413.  
  1414.         else return DefWindowProc(win, msg, wparam, lparam);
  1415.  
  1416.     default:
  1417.         return DefWindowProc(win, msg, wparam, lparam);
  1418.     }
  1419.     return 0L;
  1420. }
  1421.  
  1422. /*
  1423.  * MyErrorToString
  1424.  * Returns a pointer to a string describing the given error code.
  1425.  */
  1426. char*
  1427. MyErrorToString(HRESULT error)
  1428. {
  1429.     switch(error) {
  1430.         case DD_OK:
  1431.             /* Also includes D3D_OK and D3DRM_OK */
  1432.             return "No error.\0";
  1433.         case DDERR_ALREADYINITIALIZED:
  1434.             return "This object is already initialized.\0";
  1435.         case DDERR_BLTFASTCANTCLIP:
  1436.             return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
  1437.         case DDERR_CANNOTATTACHSURFACE:
  1438.             return "This surface can not be attached to the requested surface.\0";
  1439.         case DDERR_CANNOTDETACHSURFACE:
  1440.             return "This surface can not be detached from the requested surface.\0";
  1441.         case DDERR_CANTCREATEDC:
  1442.             return "Windows can not create any more DCs.\0";
  1443.         case DDERR_CANTDUPLICATE:
  1444.             return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
  1445.         case DDERR_CLIPPERISUSINGHWND:
  1446.             return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
  1447.         case DDERR_COLORKEYNOTSET:
  1448.             return "No src color key specified for this operation.\0";
  1449.         case DDERR_CURRENTLYNOTAVAIL:
  1450.             return "Support is currently not available.\0";
  1451.         case DDERR_DIRECTDRAWALREADYCREATED:
  1452.             return "A DirectDraw object representing this driver has already been created for this process.\0";
  1453.         case DDERR_EXCEPTION:
  1454.             return "An exception was encountered while performing the requested operation.\0";
  1455.         case DDERR_EXCLUSIVEMODEALREADYSET:
  1456.             return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
  1457.         case DDERR_GENERIC:
  1458.             return "Generic failure.\0";
  1459.         case DDERR_HEIGHTALIGN:
  1460.             return "Height of rectangle provided is not a multiple of reqd alignment.\0";
  1461.         case DDERR_HWNDALREADYSET:
  1462.             return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
  1463.         case DDERR_HWNDSUBCLASSED:
  1464.             return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
  1465.         case DDERR_IMPLICITLYCREATED:
  1466.             return "This surface can not be restored because it is an implicitly created surface.\0";
  1467.         case DDERR_INCOMPATIBLEPRIMARY:
  1468.             return "Unable to match primary surface creation request with existing primary surface.\0";
  1469.         case DDERR_INVALIDCAPS:
  1470.             return "One or more of the caps bits passed to the callback are incorrect.\0";
  1471.         case DDERR_INVALIDCLIPLIST:
  1472.             return "DirectDraw does not support the provided cliplist.\0";
  1473.         case DDERR_INVALIDDIRECTDRAWGUID:
  1474.             return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
  1475.         case DDERR_INVALIDMODE:
  1476.             return "DirectDraw does not support the requested mode.\0";
  1477.         case DDERR_INVALIDOBJECT:
  1478.             return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
  1479.         case DDERR_INVALIDPARAMS:
  1480.             return "One or more of the parameters passed to the function are incorrect.\0";
  1481.         case DDERR_INVALIDPIXELFORMAT:
  1482.             return "The pixel format was invalid as specified.\0";
  1483.         case DDERR_INVALIDPOSITION:
  1484.             return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
  1485.         case DDERR_INVALIDRECT:
  1486.             return "Rectangle provided was invalid.\0";
  1487.         case DDERR_LOCKEDSURFACES:
  1488.             return "Operation could not be carried out because one or more surfaces are locked.\0";
  1489.         case DDERR_NO3D:
  1490.             return "There is no 3D present.\0";
  1491.         case DDERR_NOALPHAHW:
  1492.             return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
  1493.         case DDERR_NOBLTHW:
  1494.             return "No blitter hardware present.\0";
  1495.         case DDERR_NOCLIPLIST:
  1496.             return "No cliplist available.\0";
  1497.         case DDERR_NOCLIPPERATTACHED:
  1498.             return "No clipper object attached to surface object.\0";
  1499.         case DDERR_NOCOLORCONVHW:
  1500.             return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
  1501.         case DDERR_NOCOLORKEY:
  1502.             return "Surface doesn't currently have a color key\0";
  1503.         case DDERR_NOCOLORKEYHW:
  1504.             return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
  1505.         case DDERR_NOCOOPERATIVELEVELSET:
  1506.             return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
  1507.         case DDERR_NODC:
  1508.             return "No DC was ever created for this surface.\0";
  1509.         case DDERR_NODDROPSHW:
  1510.             return "No DirectDraw ROP hardware.\0";
  1511.         case DDERR_NODIRECTDRAWHW:
  1512.             return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
  1513.         case DDERR_NOEMULATION:
  1514.             return "Software emulation not available.\0";
  1515.         case DDERR_NOEXCLUSIVEMODE:
  1516.             return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
  1517.         case DDERR_NOFLIPHW:
  1518.             return "Flipping visible surfaces is not supported.\0";
  1519.         case DDERR_NOGDI:
  1520.             return "There is no GDI present.\0";
  1521.         case DDERR_NOHWND:
  1522.             return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
  1523.         case DDERR_NOMIRRORHW:
  1524.             return "Operation could not be carried out because there is no hardware present or available.\0";
  1525.         case DDERR_NOOVERLAYDEST:
  1526.             return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
  1527.         case DDERR_NOOVERLAYHW:
  1528.             return "Operation could not be carried out because there is no overlay hardware present or available.\0";
  1529.         case DDERR_NOPALETTEATTACHED:
  1530.             return "No palette object attached to this surface.\0";
  1531.         case DDERR_NOPALETTEHW:
  1532.             return "No hardware support for 16 or 256 color palettes.\0";
  1533.         case DDERR_NORASTEROPHW:
  1534.             return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
  1535.         case DDERR_NOROTATIONHW:
  1536.             return "Operation could not be carried out because there is no rotation hardware present or available.\0";
  1537.         case DDERR_NOSTRETCHHW:
  1538.             return "Operation could not be carried out because there is no hardware support for stretching.\0";
  1539.         case DDERR_NOT4BITCOLOR:
  1540.             return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
  1541.         case DDERR_NOT4BITCOLORINDEX:
  1542.             return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
  1543.         case DDERR_NOT8BITCOLOR:
  1544.             return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
  1545.         case DDERR_NOTAOVERLAYSURFACE:
  1546.             return "Returned when an overlay member is called for a non-overlay surface.\0";
  1547.         case DDERR_NOTEXTUREHW:
  1548.             return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
  1549.         case DDERR_NOTFLIPPABLE:
  1550.             return "An attempt has been made to flip a surface that is not flippable.\0";
  1551.         case DDERR_NOTFOUND:
  1552.             return "Requested item was not found.\0";
  1553.         case DDERR_NOTLOCKED:
  1554.             return "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
  1555.         case DDERR_NOTPALETTIZED:
  1556.             return "The surface being used is not a palette-based surface.\0";
  1557.         case DDERR_NOVSYNCHW:
  1558.             return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
  1559.         case DDERR_NOZBUFFERHW:
  1560.             return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
  1561.         case DDERR_NOZOVERLAYHW:
  1562.             return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
  1563.         case DDERR_OUTOFCAPS:
  1564.             return "The hardware needed for the requested operation has already been allocated.\0";
  1565.         case DDERR_OUTOFMEMORY:
  1566.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1567.         case DDERR_OUTOFVIDEOMEMORY:
  1568.             return "DirectDraw does not have enough memory to perform the operation.\0";
  1569.         case DDERR_OVERLAYCANTCLIP:
  1570.             return "The hardware does not support clipped overlays.\0";
  1571.         case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
  1572.             return "Can only have ony color key active at one time for overlays.\0";
  1573.         case DDERR_OVERLAYNOTVISIBLE:
  1574.             return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
  1575.         case DDERR_PALETTEBUSY:
  1576.             return "Access to this palette is being refused because the palette is already locked by another thread.\0";
  1577.         case DDERR_PRIMARYSURFACEALREADYEXISTS:
  1578.             return "This process already has created a primary surface.\0";
  1579.         case DDERR_REGIONTOOSMALL:
  1580.             return "Region passed to Clipper::GetClipList is too small.\0";
  1581.         case DDERR_SURFACEALREADYATTACHED:
  1582.             return "This surface is already attached to the surface it is being attached to.\0";
  1583.         case DDERR_SURFACEALREADYDEPENDENT:
  1584.             return "This surface is already a dependency of the surface it is being made a dependency of.\0";
  1585.         case DDERR_SURFACEBUSY:
  1586.             return "Access to this surface is being refused because the surface is already locked by another thread.\0";
  1587.         case DDERR_SURFACEISOBSCURED:
  1588.             return "Access to surface refused because the surface is obscured.\0";
  1589.         case DDERR_SURFACELOST:
  1590.             return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
  1591.         case DDERR_SURFACENOTATTACHED:
  1592.             return "The requested surface is not attached.\0";
  1593.         case DDERR_TOOBIGHEIGHT:
  1594.             return "Height requested by DirectDraw is too large.\0";
  1595.         case DDERR_TOOBIGSIZE:
  1596.             return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
  1597.         case DDERR_TOOBIGWIDTH:
  1598.             return "Width requested by DirectDraw is too large.\0";
  1599.         case DDERR_UNSUPPORTED:
  1600.             return "Action not supported.\0";
  1601.         case DDERR_UNSUPPORTEDFORMAT:
  1602.             return "FOURCC format requested is unsupported by DirectDraw.\0";
  1603.         case DDERR_UNSUPPORTEDMASK:
  1604.             return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
  1605.         case DDERR_VERTICALBLANKINPROGRESS:
  1606.             return "Vertical blank is in progress.\0";
  1607.         case DDERR_WASSTILLDRAWING:
  1608.             return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
  1609.         case DDERR_WRONGMODE:
  1610.             return "This surface can not be restored because it was created in a different mode.\0";
  1611.         case DDERR_XALIGN:
  1612.             return "Rectangle provided was not horizontally aligned on required boundary.\0";
  1613.         case D3DERR_BADMAJORVERSION:
  1614.             return "D3DERR_BADMAJORVERSION\0";
  1615.         case D3DERR_BADMINORVERSION:
  1616.             return "D3DERR_BADMINORVERSION\0";
  1617.         case D3DERR_EXECUTE_LOCKED:
  1618.             return "D3DERR_EXECUTE_LOCKED\0";
  1619.         case D3DERR_EXECUTE_NOT_LOCKED:
  1620.             return "D3DERR_EXECUTE_NOT_LOCKED\0";
  1621.         case D3DERR_EXECUTE_CREATE_FAILED:
  1622.             return "D3DERR_EXECUTE_CREATE_FAILED\0";
  1623.         case D3DERR_EXECUTE_DESTROY_FAILED:
  1624.             return "D3DERR_EXECUTE_DESTROY_FAILED\0";
  1625.         case D3DERR_EXECUTE_LOCK_FAILED:
  1626.             return "D3DERR_EXECUTE_LOCK_FAILED\0";
  1627.         case D3DERR_EXECUTE_UNLOCK_FAILED:
  1628.             return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
  1629.         case D3DERR_EXECUTE_FAILED:
  1630.             return "D3DERR_EXECUTE_FAILED\0";
  1631.         case D3DERR_EXECUTE_CLIPPED_FAILED:
  1632.             return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
  1633.         case D3DERR_TEXTURE_NO_SUPPORT:
  1634.             return "D3DERR_TEXTURE_NO_SUPPORT\0";
  1635.         case D3DERR_TEXTURE_NOT_LOCKED:
  1636.             return "D3DERR_TEXTURE_NOT_LOCKED\0";
  1637.         case D3DERR_TEXTURE_LOCKED:
  1638.             return "D3DERR_TEXTURELOCKED\0";
  1639.         case D3DERR_TEXTURE_CREATE_FAILED:
  1640.             return "D3DERR_TEXTURE_CREATE_FAILED\0";
  1641.         case D3DERR_TEXTURE_DESTROY_FAILED:
  1642.             return "D3DERR_TEXTURE_DESTROY_FAILED\0";
  1643.         case D3DERR_TEXTURE_LOCK_FAILED:
  1644.             return "D3DERR_TEXTURE_LOCK_FAILED\0";
  1645.         case D3DERR_TEXTURE_UNLOCK_FAILED:
  1646.             return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
  1647.         case D3DERR_TEXTURE_LOAD_FAILED:
  1648.             return "D3DERR_TEXTURE_LOAD_FAILED\0";
  1649.         case D3DERR_MATRIX_CREATE_FAILED:
  1650.             return "D3DERR_MATRIX_CREATE_FAILED\0";
  1651.         case D3DERR_MATRIX_DESTROY_FAILED:
  1652.             return "D3DERR_MATRIX_DESTROY_FAILED\0";
  1653.         case D3DERR_MATRIX_SETDATA_FAILED:
  1654.             return "D3DERR_MATRIX_SETDATA_FAILED\0";
  1655.         case D3DERR_SETVIEWPORTDATA_FAILED:
  1656.             return "D3DERR_SETVIEWPORTDATA_FAILED\0";
  1657.         case D3DERR_MATERIAL_CREATE_FAILED:
  1658.             return "D3DERR_MATERIAL_CREATE_FAILED\0";
  1659.         case D3DERR_MATERIAL_DESTROY_FAILED:
  1660.             return "D3DERR_MATERIAL_DESTROY_FAILED\0";
  1661.         case D3DERR_MATERIAL_SETDATA_FAILED:
  1662.             return "D3DERR_MATERIAL_SETDATA_FAILED\0";
  1663.         case D3DERR_LIGHT_SET_FAILED:
  1664.             return "D3DERR_LIGHT_SET_FAILED\0";
  1665.         case D3DRMERR_BADOBJECT:
  1666.             return "D3DRMERR_BADOBJECT\0";
  1667.         case D3DRMERR_BADTYPE:
  1668.             return "D3DRMERR_BADTYPE\0";
  1669.         case D3DRMERR_BADALLOC:
  1670.             return "D3DRMERR_BADALLOC\0";
  1671.         case D3DRMERR_FACEUSED:
  1672.             return "D3DRMERR_FACEUSED\0";
  1673.         case D3DRMERR_NOTFOUND:
  1674.             return "D3DRMERR_NOTFOUND\0";
  1675.         case D3DRMERR_NOTDONEYET:
  1676.             return "D3DRMERR_NOTDONEYET\0";
  1677.         case D3DRMERR_FILENOTFOUND:
  1678.             return "The file was not found.\0";
  1679.         case D3DRMERR_BADFILE:
  1680.             return "D3DRMERR_BADFILE\0";
  1681.         case D3DRMERR_BADDEVICE:
  1682.             return "D3DRMERR_BADDEVICE\0";
  1683.         case D3DRMERR_BADVALUE:
  1684.             return "D3DRMERR_BADVALUE\0";
  1685.         case D3DRMERR_BADMAJORVERSION:
  1686.             return "D3DRMERR_BADMAJORVERSION\0";
  1687.         case D3DRMERR_BADMINORVERSION:
  1688.             return "D3DRMERR_BADMINORVERSION\0";
  1689.         case D3DRMERR_UNABLETOEXECUTE:
  1690.             return "D3DRMERR_UNABLETOEXECUTE\0";
  1691.         default:
  1692.             return "Unrecognized error value.\0";
  1693.     }
  1694. }
  1695.