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