home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / directx2 / sdk / samples / twist / twist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-28  |  15.9 KB  |  479 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: twist.c
  6.  *
  7.  ***************************************************************************/
  8.  
  9. #include "d3d.h"
  10. #include "math.h"
  11. #include "malloc.h"
  12. #include "d3dmacs.h"
  13. #include "d3ddemo.h"
  14.  
  15. /*
  16.  * Globals to keep track of execute buffer
  17.  */
  18. static D3DEXECUTEDATA d3dExData;
  19. static LPDIRECT3DEXECUTEBUFFER lpD3DExBuf;
  20. static D3DEXECUTEBUFFERDESC debDesc;
  21. LPDIRECT3DMATERIAL lpbmat; /* Object for background material */
  22. LPDIRECT3DLIGHT lpD3DLight; /* object for light */
  23. LPDIRECT3DMATERIAL lpred_mat, lpblue_mat;           /* Objects for materials */
  24.  
  25. /*
  26.  * Global projection, view, world and identity matricies
  27.  */
  28. D3DMATRIXHANDLE hProj;
  29. D3DMATRIXHANDLE hView;
  30. D3DMATRIXHANDLE hSpin;
  31. D3DMATRIXHANDLE hDSpin;
  32. D3DMATRIXHANDLE hWorld;
  33. D3DMATRIXHANDLE hWorld1;
  34. D3DMATRIXHANDLE hWorld2;
  35. D3DMATRIXHANDLE hDWorld1;
  36. D3DMATRIXHANDLE hDWorld2;
  37.  
  38. D3DMATRIX proj = {
  39.     D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  40.     D3DVAL(0.0), D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0),
  41.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(1.0),
  42.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0)
  43. };
  44. D3DMATRIX view = {
  45.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  46.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  47.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  48.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(10.0), D3DVAL(1.0)
  49. };
  50. D3DMATRIX spin;
  51. D3DMATRIX dspin;
  52. D3DMATRIX world;
  53. D3DMATRIX world1;
  54. D3DMATRIX dworld1;
  55. D3DMATRIX world2;
  56. D3DMATRIX dworld2;
  57. D3DMATRIX identity = {
  58.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  59.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  60.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  61.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
  62. };
  63.  
  64. /*
  65.  * A structure which holds the object's data
  66.  */
  67. struct {
  68.     D3DMATERIALHANDLE hred_mat, hblue_mat; /* two material handles */
  69.     D3DTEXTUREHANDLE hTex;                 /* texture map handles  */
  70.     LPD3DVERTEX lpV;                       /* object's vertices    */
  71.     LPD3DTRIANGLE lpTri;                   /* object's triangles   */
  72.     int num_vertices, num_faces;
  73. } objData;
  74.  
  75. #define PI 3.14159265359
  76.  
  77. void
  78. OverrideDefaults(Defaults* defaults)
  79. {
  80.     lstrcpy(defaults->Name, "Twist D3D Example");
  81. }
  82.  
  83. /*
  84.  * Two functions to rotate a number of D3DVERTEX points.  Each makes use of
  85.  * the TransformVertices function.
  86.  */
  87. void 
  88. XRotateD3DVERTEX(float theta, int count, LPD3DVERTEX lpV)
  89. {
  90.     float st, ct;
  91.     int i;
  92.  
  93.     st = (float)sin(theta); ct = (float)cos(theta);
  94.     for (i = 0; i < count; i++) {
  95.         float y, z;
  96.         y = lpV[i].y; z = lpV[i].z;
  97.         lpV[i].y = ct * y + st * z;
  98.         lpV[i].z = -st * y + ct * z;
  99.         y = lpV[i].ny; z = lpV[i].nz;
  100.         lpV[i].ny = ct * y + st * z;
  101.         lpV[i].nz = -st * y + ct * z;
  102.     }
  103. }
  104.  
  105.  
  106. /*
  107.  * Renders the scene
  108.  */
  109. BOOL
  110. RenderScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView,
  111.             LPD3DRECT lpExtent)
  112. {
  113.     HRESULT ddrval;
  114.  
  115.     /*
  116.      * Execute the instruction buffer and blt
  117.      */
  118.     ddrval = lpDev->lpVtbl->BeginScene(lpDev);
  119.     if (ddrval != D3D_OK)
  120.         return FALSE;
  121.     ddrval = lpDev->lpVtbl->Execute(lpDev, lpD3DExBuf, lpView, D3DEXECUTE_CLIPPED);
  122.     if (ddrval != D3D_OK)
  123.         return FALSE;
  124.     ddrval = lpDev->lpVtbl->EndScene(lpDev);
  125.     if (ddrval != D3D_OK)
  126.         return FALSE;
  127.     ddrval = lpD3DExBuf->lpVtbl->GetExecuteData(lpD3DExBuf, &d3dExData);
  128.     if (ddrval != D3D_OK)
  129.         return FALSE;
  130.     /*
  131.      * Return the extent
  132.      */
  133.     *lpExtent = d3dExData.dsStatus.drExtent;
  134.     return TRUE;
  135. }
  136.  
  137.  
  138. void
  139. ReleaseScene(void)
  140. {
  141.     if (objData.lpTri)
  142.         free(objData.lpTri);
  143.     if (objData.lpV)
  144.         free(objData.lpV);
  145. }
  146.  
  147. void
  148. ReleaseView(LPDIRECT3DVIEWPORT lpView)
  149. {
  150.     if (lpView)
  151.         lpView->lpVtbl->DeleteLight(lpView, lpD3DLight);
  152.     RELEASE(lpbmat);
  153.     RELEASE(lpred_mat);
  154.     RELEASE(lpblue_mat);
  155.     RELEASE(lpD3DExBuf);
  156.     RELEASE(lpD3DLight);
  157. }
  158.  
  159. /*
  160.  * Builds the scene
  161.  */
  162. BOOL
  163. InitScene(void)
  164. {
  165.     int i;
  166.     /*
  167.      * Generate the sphere which will be used as the twisted object.  Scale
  168.      * one axis long.  Rotate the sphere around the x axis so the end caps
  169.      * are around the z axis (for effect).  Stretch one end of the sphere 
  170.      * out to allow an easier view of the twisting.
  171.      */
  172.     if (!(GenerateSphere((float)1.7, 9, 15, (float)1.0, (float)2.0,
  173.                          (float)1.0, &objData.lpV, &objData.lpTri,
  174.                          &objData.num_vertices, &objData.num_faces)))
  175.                                 return FALSE;
  176.                                 
  177.     /*
  178.      * As we are going to twist the sphere the quads in the sphere will
  179.      * no longer stay flat. We need to change all start flat setting to just
  180.      * start.
  181.      */
  182.     for (i = 0; i < objData.num_faces; i++) {
  183.         if (((objData.lpTri[i].wFlags & 0x1f) < 30) &&
  184.             ((objData.lpTri[i].wFlags & 0x1f) > 0)) {
  185.             objData.lpTri[i].wFlags &= ~0x1f;
  186.         }
  187.     }
  188.         
  189.     XRotateD3DVERTEX((float)(PI / 2.0), objData.num_vertices, objData.lpV);
  190.     for (i = 0; i < objData.num_vertices; i++)
  191.         if (objData.lpV[i].z > 0) objData.lpV[i].z += (float)2.0;
  192.     return TRUE;
  193. }
  194.  
  195. /*
  196.  * Initializes the execute buffer for rendering.
  197.  */
  198. #define DT 0.05 /* amount to twist, different from spin for effect */
  199. #define DS 0.08 /* amount to spin world each time */
  200. BOOL
  201. InitView(LPDIRECTDRAW lpDD, LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpDev,
  202.            LPDIRECT3DVIEWPORT lpView, int NumTextures,
  203.            LPD3DTEXTUREHANDLE TextureHandle)
  204. {
  205.     /* Variables for execute buffer generation */
  206.     LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf;
  207.     LPD3DTRIANGLE lpTri;
  208.     LPVOID lpBufStart, lpInsStart, lpPointer;
  209.     size_t size;
  210.  
  211.     /* Materials and lights */
  212.     D3DLIGHT light;                                     
  213.     D3DMATERIAL bmat;
  214.     D3DMATERIALHANDLE hbmat;
  215.     D3DMATERIAL red_mat, blue_mat;
  216.  
  217.     int i;
  218.     float ct, st;
  219.  
  220.     HRESULT ddrval;
  221.  
  222.     /*
  223.      * Set background to black material
  224.      */
  225.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpbmat, NULL) != D3D_OK)
  226.         return FALSE;
  227.     memset(&bmat, 0, sizeof(D3DMATERIAL));
  228.     bmat.dwSize = sizeof(D3DMATERIAL);
  229.     bmat.dwRampSize = 1;
  230.     ddrval = lpbmat->lpVtbl->SetMaterial(lpbmat, &bmat);
  231.     ddrval = lpbmat->lpVtbl->GetHandle(lpbmat, lpDev, &hbmat);
  232.     ddrval = lpView->lpVtbl->SetBackground(lpView, hbmat);
  233.  
  234.     /*
  235.      * Set the view, world and projection matrices
  236.      */
  237.     MAKE_MATRIX(lpDev, hView, view);
  238.     MAKE_MATRIX(lpDev, hProj, proj);
  239.     MAKE_MATRIX(lpDev, hWorld, identity);
  240.     MAKE_MATRIX(lpDev, hSpin, identity);
  241.     MAKE_MATRIX(lpDev, hWorld1, identity);
  242.     MAKE_MATRIX(lpDev, hWorld2, identity);
  243.  
  244.     /*
  245.      * Setup the matrices which spin the buffer
  246.      */
  247.     ct = D3DVAL(cos(DS));
  248.     st = D3DVAL(sin(DS));
  249.     dspin = identity;
  250.     dspin._11 = ct;
  251.     dspin._13 = -st;
  252.     dspin._31 = st;
  253.     dspin._33 = ct;
  254.     MAKE_MATRIX(lpDev, hDSpin, dspin);
  255.  
  256.     ct = D3DVAL(cos(DT));
  257.     st = D3DVAL(sin(DT));
  258.     dworld1 = identity;
  259.     dworld1._11 = ct;
  260.     dworld1._21 = -st;
  261.     dworld1._12 = st;
  262.     dworld1._22 = ct;
  263.     MAKE_MATRIX(lpDev, hDWorld1, dworld1);
  264.     
  265.     ct = D3DVAL(cos(-DT));
  266.     st = D3DVAL(sin(-DT));
  267.     dworld2 = identity;
  268.     dworld2._11 = ct;
  269.     dworld2._21 = -st;
  270.     dworld2._12 = st;
  271.     dworld2._22 = ct;
  272.     MAKE_MATRIX(lpDev, hDWorld2, dworld2);
  273.  
  274.     /*
  275.      * Use an execute buffer to set some transform state
  276.      */
  277.     size = 0;
  278.     size += sizeof(D3DINSTRUCTION) * 3;
  279.     size += sizeof(D3DSTATE) * 3;
  280.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  281.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  282.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  283.     debDesc.dwBufferSize = size;
  284.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExCmdBuf,
  285.                                            NULL) != D3D_OK)
  286.         return FALSE;
  287.     if (lpD3DExCmdBuf->lpVtbl->Lock(lpD3DExCmdBuf, &debDesc) != D3D_OK)
  288.         return FALSE;
  289.     lpBufStart = debDesc.lpData;
  290.     memset(lpBufStart, 0, size);
  291.     lpPointer = lpBufStart;
  292.  
  293.     lpInsStart = lpPointer;
  294.     OP_STATE_TRANSFORM(2, lpPointer);
  295.         STATE_DATA(D3DTRANSFORMSTATE_PROJECTION, hProj, lpPointer);
  296.         STATE_DATA(D3DTRANSFORMSTATE_VIEW, hView, lpPointer);
  297.     OP_STATE_LIGHT(1, lpPointer);
  298.         STATE_DATA(D3DLIGHTSTATE_AMBIENT, RGBA_MAKE(20, 20, 20, 20), lpPointer);
  299.     OP_EXIT(lpPointer);
  300.     
  301.     lpD3DExCmdBuf->lpVtbl->Unlock(lpD3DExCmdBuf);
  302.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  303.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  304.     d3dExData.dwInstructionOffset = (ULONG) 0;
  305.     d3dExData.dwInstructionLength = (ULONG) ((char *)lpPointer - (char *)lpInsStart);
  306.     lpD3DExCmdBuf->lpVtbl->SetExecuteData(lpD3DExCmdBuf, &d3dExData);
  307.     ddrval = lpDev->lpVtbl->BeginScene(lpDev);
  308.     if (ddrval != D3D_OK)
  309.         return FALSE;
  310.     lpDev->lpVtbl->Execute(lpDev, lpD3DExCmdBuf, lpView, D3DEXECUTE_UNCLIPPED);
  311.     ddrval = lpDev->lpVtbl->EndScene(lpDev);
  312.     if (ddrval != D3D_OK)
  313.         return FALSE;
  314.     lpD3DExCmdBuf->lpVtbl->Release(lpD3DExCmdBuf);
  315.  
  316.     /*
  317.      * Create each material, set its description and obtain a handle to it.
  318.      */
  319.     objData.hTex = TextureHandle[1];
  320.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpred_mat, NULL) != D3D_OK)
  321.         return FALSE;
  322.     memset(&red_mat, 0, sizeof(D3DMATERIAL));
  323.     red_mat.dwSize = sizeof(D3DMATERIAL);
  324.     red_mat.diffuse.r = (D3DVALUE)1.0;
  325.     red_mat.diffuse.g = (D3DVALUE)0.8;
  326.     red_mat.diffuse.b = (D3DVALUE)0.8;
  327.     red_mat.diffuse.a = (D3DVALUE)1.0;
  328.     red_mat.ambient.r = (D3DVALUE)1.0;
  329.     red_mat.ambient.g = (D3DVALUE)0.0;
  330.     red_mat.ambient.b = (D3DVALUE)0.0;
  331.     red_mat.specular.r = (D3DVALUE)1.0;
  332.     red_mat.specular.g = (D3DVALUE)1.0;
  333.     red_mat.specular.b = (D3DVALUE)1.0;
  334.     red_mat.power = (float)20.0;
  335.     red_mat.dwRampSize = 16;
  336.     red_mat.hTexture = objData.hTex;
  337.     lpred_mat->lpVtbl->SetMaterial(lpred_mat, &red_mat);
  338.     lpred_mat->lpVtbl->GetHandle(lpred_mat, lpDev, &objData.hred_mat);
  339.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpblue_mat, NULL) != D3D_OK)
  340.         return FALSE;
  341.     memset(&blue_mat, 0, sizeof(D3DMATERIAL));
  342.     blue_mat.dwSize = sizeof(D3DMATERIAL);
  343.     blue_mat.diffuse.r = (D3DVALUE)0.5;
  344.     blue_mat.diffuse.g = (D3DVALUE)0.5;
  345.     blue_mat.diffuse.b = (D3DVALUE)1.0;
  346.     blue_mat.diffuse.a = (D3DVALUE)1.0;
  347.     blue_mat.ambient.r = (D3DVALUE)0.0;
  348.     blue_mat.ambient.g = (D3DVALUE)0.0;
  349.     blue_mat.ambient.b = (D3DVALUE)1.0;
  350.     blue_mat.specular.r = (D3DVALUE)1.0;
  351.     blue_mat.specular.g = (D3DVALUE)1.0;
  352.     blue_mat.specular.b = (D3DVALUE)1.0;
  353.     blue_mat.power = (float)20.0;
  354.     blue_mat.dwRampSize = 16;
  355.     blue_mat.hTexture = objData.hTex;
  356.     lpblue_mat->lpVtbl->SetMaterial(lpblue_mat, &blue_mat);
  357.     lpblue_mat->lpVtbl->GetHandle(lpblue_mat, lpDev, &objData.hblue_mat);
  358.  
  359.     /*
  360.      * Create the main execute buffer
  361.      */
  362.     size = sizeof(D3DVERTEX) * objData.num_vertices * 2; /* two copies */
  363.     size += sizeof(D3DPROCESSVERTICES) * 2;
  364.     size += sizeof(D3DSTATUS) * 1;
  365.     size += sizeof(D3DINSTRUCTION) * 16;
  366.     size += sizeof(D3DSTATE) * 6;
  367.     size += sizeof(D3DMATRIXMULTIPLY) * 5;
  368.     size += sizeof(D3DTRIANGLE) * objData.num_faces;
  369.  
  370.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  371.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  372.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  373.     debDesc.dwBufferSize = size;
  374.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExBuf, 
  375.                                            NULL) != D3D_OK)
  376.                                                return FALSE;
  377.     if (lpD3DExBuf->lpVtbl->Lock(lpD3DExBuf, &debDesc) != D3D_OK)
  378.         return FALSE;
  379.     lpBufStart = debDesc.lpData;
  380.     memset(lpBufStart, 0, size);
  381.     lpPointer = lpBufStart;
  382.     /*
  383.      * Copy two sets of the vertices into the buffer for the first render.
  384.      */
  385.     VERTEX_DATA(objData.lpV, objData.num_vertices, lpPointer);
  386.     VERTEX_DATA(objData.lpV, objData.num_vertices, lpPointer);
  387.  
  388.     lpInsStart = lpPointer;
  389.     OP_SET_STATUS(D3DSETSTATUS_ALL, D3DSTATUS_DEFAULT, 2048, 2048, 0, 0, lpPointer);
  390.     OP_MATRIX_MULTIPLY(1, lpPointer);
  391.         MATRIX_MULTIPLY_DATA(hDSpin, hSpin, hSpin, lpPointer);
  392.     OP_STATE_LIGHT(1, lpPointer);
  393.         STATE_DATA(D3DLIGHTSTATE_MATERIAL, objData.hblue_mat, lpPointer);
  394.     OP_MATRIX_MULTIPLY(1, lpPointer);
  395.         MATRIX_MULTIPLY_DATA(hWorld1, hDWorld1, hWorld1, lpPointer);
  396.     OP_MATRIX_MULTIPLY(1, lpPointer);
  397.         MATRIX_MULTIPLY_DATA(hWorld1, hSpin, hWorld, lpPointer);
  398.     OP_STATE_TRANSFORM(1, lpPointer);
  399.         STATE_DATA(D3DTRANSFORMSTATE_WORLD, hWorld, lpPointer);
  400.     OP_PROCESS_VERTICES(1, lpPointer);
  401.         PROCESSVERTICES_DATA(D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, objData.num_vertices, lpPointer);
  402.  
  403.     OP_STATE_LIGHT(1, lpPointer);
  404.         STATE_DATA(D3DLIGHTSTATE_MATERIAL, objData.hred_mat, lpPointer);
  405.     OP_MATRIX_MULTIPLY(1, lpPointer);
  406.         MATRIX_MULTIPLY_DATA(hWorld2, hDWorld2, hWorld2, lpPointer);
  407.     OP_MATRIX_MULTIPLY(1, lpPointer);
  408.         MATRIX_MULTIPLY_DATA(hWorld2, hSpin, hWorld, lpPointer);
  409.     OP_STATE_TRANSFORM(1, lpPointer);
  410.         STATE_DATA(D3DTRANSFORMSTATE_WORLD, hWorld, lpPointer);
  411.     OP_PROCESS_VERTICES(1, lpPointer);
  412.         PROCESSVERTICES_DATA(D3DPROCESSVERTICES_TRANSFORMLIGHT, objData.num_vertices, objData.num_vertices, lpPointer);
  413.     OP_STATE_RENDER(2, lpPointer);
  414.         STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, objData.hTex, lpPointer);
  415.         STATE_DATA(D3DRENDERSTATE_WRAPU, TRUE, lpPointer);
  416.     /*
  417.      * Make sure that the triangle data (not OP) will be QWORD aligned
  418.      */
  419.     if (QWORD_ALIGNED(lpPointer)) {
  420.         OP_NOP(lpPointer);
  421.     }
  422.     OP_TRIANGLE_LIST(objData.num_faces, lpPointer);
  423.         lpTri = lpPointer;
  424.         TRIANGLE_LIST_DATA(objData.lpTri, objData.num_faces, lpPointer);
  425.     /*
  426.      * If the z coordinate of a vertex referenced by a triangle is > 0, 
  427.      * make the triangle reference the same vertex in the second copy of 
  428.      * the vetices.
  429.      */ 
  430.     for (i = 0; i < objData.num_faces; i++) {   
  431.         if (objData.lpV[lpTri->v1].z > 0)
  432.             lpTri->v1 += objData.num_vertices;
  433.         if (objData.lpV[lpTri->v2].z > 0)
  434.             lpTri->v2 += objData.num_vertices;
  435.         if (objData.lpV[lpTri->v3].z > 0)
  436.             lpTri->v3 += objData.num_vertices;
  437.         lpTri++;
  438.     }
  439.     OP_EXIT(lpPointer);
  440.  
  441.     lpD3DExBuf->lpVtbl->Unlock(lpD3DExBuf);
  442.     /*
  443.      * Setup the execute data describing the buffer
  444.      */
  445.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  446.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  447.     d3dExData.dwVertexCount = objData.num_vertices * 2;
  448.     d3dExData.dwInstructionOffset = (ULONG)((char *)lpInsStart - (char *)lpBufStart);
  449.     d3dExData.dwInstructionLength = (ULONG)((char*)lpPointer - (char *)lpInsStart);
  450.     lpD3DExBuf->lpVtbl->SetExecuteData(lpD3DExBuf, &d3dExData);
  451.  
  452.     /*
  453.      * Add one light.
  454.      */
  455.     memset(&light, 0, sizeof(D3DLIGHT));
  456.     light.dwSize = sizeof(D3DLIGHT);
  457.     light.dltType = D3DLIGHT_DIRECTIONAL;
  458.     light.dcvColor.r = D3DVAL(0.9);
  459.     light.dcvColor.g = D3DVAL(0.9);
  460.     light.dcvColor.b = D3DVAL(0.9);
  461.     light.dcvColor.a = D3DVAL(1.0);
  462.     light.dvDirection.x = D3DVALP(0.0, 12);
  463.     light.dvDirection.y = D3DVALP(0.0, 12);
  464.     light.dvDirection.z = D3DVALP(1.0, 12);
  465.     light.dvAttenuation0 = (float)1.0;
  466.     light.dvAttenuation1 = (float)0.0;
  467.     light.dvAttenuation2 = (float)0.0;
  468.     if (lpD3D->lpVtbl->CreateLight(lpD3D, &lpD3DLight, NULL) != D3D_OK)
  469.         return FALSE;
  470.     if (lpD3DLight->lpVtbl->SetLight(lpD3DLight, &light) != D3D_OK)
  471.         return FALSE;
  472.     if (lpView->lpVtbl->AddLight(lpView, lpD3DLight) != D3D_OK)
  473.         return FALSE;
  474.  
  475.     return TRUE;
  476. }
  477.  
  478.  
  479.