home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / SPHERE / SPHERE.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  12KB  |  346 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
  4.  *
  5.  *  File: sphere.c
  6.  *
  7.  ***************************************************************************/
  8.  
  9. #include <math.h>
  10. #include <malloc.h>
  11. #include <d3d.h>
  12. #include "d3ddemo.h"
  13.  
  14. /*
  15.  * Globals to keep track of execute buffer
  16.  */
  17. static D3DEXECUTEDATA d3dExData;
  18. static LPDIRECT3DEXECUTEBUFFER lpD3DExBuf;
  19. static D3DEXECUTEBUFFERDESC debDesc;
  20. /*
  21.  * Gobals for materials and lights
  22.  */
  23. LPDIRECT3DMATERIAL lpbmat;
  24. LPDIRECT3DMATERIAL lpmat;
  25. LPDIRECT3DLIGHT lpD3DLight;             
  26. /*
  27.  * Global projection, view, world and identity matricies
  28.  */
  29. D3DMATRIXHANDLE hProj;
  30. D3DMATRIXHANDLE hView;
  31. D3DMATRIXHANDLE hWorld;
  32. D3DMATRIXHANDLE hDWorld;
  33.  
  34. D3DMATRIX proj = {
  35.     D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  36.     D3DVAL(0.0), D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0),
  37.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(1.0),
  38.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0)
  39. };
  40. D3DMATRIX view = {
  41.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  42.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  43.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  44.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(7.0), D3DVAL(1.0)
  45. };
  46. D3DMATRIX world= {
  47.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  48.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  49.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  50.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
  51. };
  52. D3DMATRIX identity = {
  53.     D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
  54.     D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
  55.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
  56.     D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0)
  57. };
  58.  
  59. /*
  60.  * A structure which holds the object's data
  61.  */
  62. struct {
  63.     D3DMATERIALHANDLE hmat;                /* material handle      */
  64.     D3DTEXTUREHANDLE hTex;                 /* texture map handles  */
  65.     LPD3DVERTEX lpV;                       /* object's vertices    */
  66.     LPD3DTRIANGLE lpTri;                   /* object's triangles   */
  67.     int num_vertices, num_faces;
  68. } objData;
  69.  
  70. #define PI 3.14159265359
  71. #define DS 0.08 /* amount to spin world each time */
  72.  
  73. void
  74. OverrideDefaults(Defaults* defaults)
  75. {
  76.     lstrcpy(defaults->Name, "Sphere D3D Example");
  77. }
  78.  
  79. /*
  80.  * Each frame, renders the scene and calls mod_buffer to modify the object
  81.  * for the next frame.
  82.  */
  83. BOOL
  84. RenderScene(LPDIRECT3DDEVICE lpDev, LPDIRECT3DVIEWPORT lpView,
  85.             LPD3DRECT lpExtent)
  86. {
  87.     /*
  88.      * Execute the instruction buffer
  89.      */
  90.     if (lpDev->lpVtbl->BeginScene(lpDev) != D3D_OK)
  91.         return FALSE;
  92.     if (lpDev->lpVtbl->Execute(lpDev, lpD3DExBuf,
  93.                                lpView, D3DEXECUTE_UNCLIPPED) != D3D_OK)
  94.         return FALSE;
  95.     if (lpDev->lpVtbl->EndScene(lpDev) != D3D_OK)
  96.         return FALSE;
  97.     if (lpD3DExBuf->lpVtbl->GetExecuteData(lpD3DExBuf, &d3dExData)!= D3D_OK)
  98.         return FALSE;
  99.     *lpExtent = d3dExData.dsStatus.drExtent;
  100.  
  101.     return TRUE;
  102. }
  103.  
  104. BOOL
  105. InitScene(void)
  106. {
  107.     /*
  108.      * Generate the sphere.
  109.      */
  110.     if (!(GenerateSphere((float)2.2, 18, 20, (float)1.0, (float)1.0,
  111.                          (float)1.0, &objData.lpV, &objData.lpTri,
  112.                          &objData.num_vertices, &objData.num_faces)))
  113.                                 return FALSE;
  114.     return TRUE;
  115. }
  116.  
  117. void
  118. ReleaseScene(void)
  119. {
  120.     if (objData.lpV)
  121.         free(objData.lpV);
  122.     if (objData.lpTri)
  123.         free(objData.lpTri);
  124. }
  125.  
  126. /*
  127.  * Release the memory allocated for the scene and all D3D objects created.
  128.  */
  129. void
  130. ReleaseView(LPDIRECT3DVIEWPORT lpView)
  131. {
  132.     if (lpView)
  133.         lpView->lpVtbl->DeleteLight(lpView, lpD3DLight);
  134.     RELEASE(lpD3DLight);
  135.     RELEASE(lpD3DExBuf);
  136.     RELEASE(lpmat);
  137.     RELEASE(lpbmat);
  138. }
  139.  
  140. /*
  141.  * Builds the scene and initializes the execute buffer for rendering.  Returns 0 on failure.
  142.  */
  143. BOOL
  144. InitView(LPDIRECTDRAW lpDD, LPDIRECT3D lpD3D, LPDIRECT3DDEVICE lpDev,
  145.            LPDIRECT3DVIEWPORT lpView, int NumTextures,
  146.            LPD3DTEXTUREHANDLE TextureHandle)
  147. {
  148.     /* Pointers into the exectue buffer. */
  149.     LPVOID lpBufStart, lpInsStart, lpPointer;
  150.     LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf;
  151.     size_t size;
  152.  
  153.     /* Light and materials */
  154.     D3DLIGHT light;                                     
  155.     D3DMATERIAL bmat;
  156.     D3DMATERIALHANDLE hbmat;
  157.     D3DMATERIAL mat;
  158.  
  159.     D3DMATRIX dworld;
  160.     float ct, st;
  161.  
  162.     /*
  163.      * Set the view, world and projection matrices
  164.      */
  165.     MAKE_MATRIX(lpDev, hView, view);
  166.     MAKE_MATRIX(lpDev, hProj, proj);
  167.     MAKE_MATRIX(lpDev, hWorld, world);
  168.     /*
  169.      * Create a buffer for matrix set commands etc.
  170.      */
  171.     size = 0;
  172.     size += sizeof(D3DINSTRUCTION) * 3;
  173.     size += sizeof(D3DSTATE) * 4;
  174.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  175.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  176.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  177.     debDesc.dwBufferSize = size;
  178.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExCmdBuf,
  179.                                            NULL) != D3D_OK)
  180.         return FALSE;
  181.     if (lpD3DExCmdBuf->lpVtbl->Lock(lpD3DExCmdBuf, &debDesc) != D3D_OK)
  182.         return FALSE;
  183.     lpBufStart = debDesc.lpData;
  184.     memset(lpBufStart, 0, size);
  185.     lpPointer = lpBufStart;
  186.  
  187.     lpInsStart = lpPointer;
  188.     OP_STATE_TRANSFORM(3, lpPointer);
  189.         STATE_DATA(D3DTRANSFORMSTATE_WORLD, hWorld, lpPointer);
  190.         STATE_DATA(D3DTRANSFORMSTATE_VIEW, hView, lpPointer);
  191.         STATE_DATA(D3DTRANSFORMSTATE_PROJECTION, hProj, lpPointer);
  192.     OP_STATE_LIGHT(1, lpPointer);
  193.         STATE_DATA(D3DLIGHTSTATE_AMBIENT, RGBA_MAKE(10, 10, 10, 10), lpPointer);
  194.     OP_EXIT(lpPointer);
  195.     /*
  196.      * Setup the execute data describing the buffer
  197.      */
  198.     lpD3DExCmdBuf->lpVtbl->Unlock(lpD3DExCmdBuf);
  199.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  200.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  201.     d3dExData.dwInstructionOffset = (ULONG) 0;
  202.     d3dExData.dwInstructionLength = (ULONG) ((char*)lpPointer - (char*)lpInsStart);
  203.     lpD3DExCmdBuf->lpVtbl->SetExecuteData(lpD3DExCmdBuf, &d3dExData);
  204.     lpDev->lpVtbl->BeginScene(lpDev);
  205.     lpDev->lpVtbl->Execute(lpDev, lpD3DExCmdBuf, lpView, D3DEXECUTE_UNCLIPPED);
  206.     lpDev->lpVtbl->EndScene(lpDev);
  207.     /*
  208.      * We are done with the command buffer.
  209.      */
  210.     lpD3DExCmdBuf->lpVtbl->Release(lpD3DExCmdBuf);
  211.     /*
  212.      * Set background to black material
  213.      */
  214.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpbmat, NULL) != D3D_OK)
  215.         return FALSE;
  216.     memset(&bmat, 0, sizeof(D3DMATERIAL));
  217.     bmat.dwSize = sizeof(D3DMATERIAL);
  218.     bmat.dwRampSize = 1;
  219.     lpbmat->lpVtbl->SetMaterial(lpbmat, &bmat);
  220.     lpbmat->lpVtbl->GetHandle(lpbmat, lpDev, &hbmat);
  221.     lpView->lpVtbl->SetBackground(lpView, hbmat);
  222.     /*
  223.      * Create a material, set its description and obtain a handle to it.
  224.      */
  225.     objData.hTex = TextureHandle[1];
  226.     if (lpD3D->lpVtbl->CreateMaterial(lpD3D, &lpmat, NULL) != D3D_OK)
  227.         return FALSE;
  228.     memset(&mat, 0, sizeof(D3DMATERIAL));
  229.     mat.dwSize = sizeof(D3DMATERIAL);
  230.     mat.diffuse.r = (D3DVALUE)1.0;
  231.     mat.diffuse.g = (D3DVALUE)1.0;
  232.     mat.diffuse.b = (D3DVALUE)1.0;
  233.     mat.diffuse.a = (D3DVALUE)1.0;
  234.     mat.ambient.r = (D3DVALUE)0.0;
  235.     mat.ambient.g = (D3DVALUE)0.0;
  236.     mat.ambient.b = (D3DVALUE)1.0;
  237.     mat.specular.r = (D3DVALUE)1.0;
  238.     mat.specular.g = (D3DVALUE)1.0;
  239.     mat.specular.b = (D3DVALUE)1.0;
  240.     mat.power = (float)40.0;
  241.     mat.dwRampSize = 32;
  242.     mat.hTexture = objData.hTex;
  243.     lpmat->lpVtbl->SetMaterial(lpmat, &mat);
  244.     lpmat->lpVtbl->GetHandle(lpmat, lpDev, &objData.hmat);
  245.     /*
  246.      * Create the matrix which spins the sphere
  247.      */
  248.     ct = D3DVAL(cos(DS));
  249.     st = D3DVAL(sin(DS));
  250.     dworld = identity;
  251.     dworld._11 = ct;
  252.     dworld._13 = -st;
  253.     dworld._31 = st;
  254.     dworld._33 = ct;
  255.     MAKE_MATRIX(lpDev, hDWorld, dworld);
  256.     /*
  257.      * Create the main execute buffer
  258.      */
  259.     size = sizeof(D3DVERTEX) * objData.num_vertices;
  260.     size += sizeof(D3DPROCESSVERTICES) * 1;
  261.     size += sizeof(D3DSTATUS) * 1;
  262.     size += sizeof(D3DINSTRUCTION) * 8;
  263.     size += sizeof(D3DSTATE) * 5;
  264.     size += sizeof(D3DMATRIXMULTIPLY) * 1;
  265.     size += sizeof(D3DTRIANGLE) * objData.num_faces;
  266.     memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  267.     debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  268.     debDesc.dwFlags = D3DDEB_BUFSIZE;
  269.     debDesc.dwBufferSize = size;
  270.     if (lpDev->lpVtbl->CreateExecuteBuffer(lpDev, &debDesc, &lpD3DExBuf, 
  271.                                            NULL) != D3D_OK)
  272.                                                return FALSE;
  273.     /*
  274.      * lock it so it can be filled
  275.      */
  276.     if (lpD3DExBuf->lpVtbl->Lock(lpD3DExBuf, &debDesc) != D3D_OK)
  277.         return FALSE;
  278.     lpBufStart = debDesc.lpData;
  279.     memset(lpBufStart, 0, size);
  280.     lpPointer = lpBufStart;
  281.  
  282.     VERTEX_DATA(objData.lpV, objData.num_vertices, lpPointer);
  283.     /*
  284.      * Save the location of the first instruction and add instructions to 
  285.      * execute buffer.
  286.      */
  287.     lpInsStart = lpPointer;
  288.     OP_STATE_LIGHT(1, lpPointer);
  289.         STATE_DATA(D3DLIGHTSTATE_MATERIAL, objData.hmat, lpPointer);
  290.     OP_MATRIX_MULTIPLY(1, lpPointer);
  291.         MATRIX_MULTIPLY_DATA(hDWorld, hWorld, hWorld, lpPointer);
  292.         
  293.     OP_SET_STATUS(D3DSETSTATUS_ALL, D3DSTATUS_DEFAULT, 2048, 2048, 0, 0, lpPointer);
  294.     
  295.     OP_PROCESS_VERTICES(1, lpPointer);
  296.         PROCESSVERTICES_DATA(D3DPROCESSVERTICES_TRANSFORMLIGHT, 0, objData.num_vertices, lpPointer);
  297.     OP_STATE_RENDER(2, lpPointer);
  298.         STATE_DATA(D3DRENDERSTATE_TEXTUREHANDLE, objData.hTex, lpPointer);
  299.         STATE_DATA(D3DRENDERSTATE_WRAPU, TRUE, lpPointer);
  300.     /*
  301.      * Make sure that the triangle data (not OP) will be QWORD aligned
  302.      */
  303.     if (QWORD_ALIGNED(lpPointer)) {
  304.         OP_NOP(lpPointer);
  305.     }
  306.     OP_TRIANGLE_LIST(objData.num_faces, lpPointer);
  307.         TRIANGLE_LIST_DATA(objData.lpTri, objData.num_faces, lpPointer);
  308.     OP_EXIT(lpPointer);
  309.     /*
  310.      * Setup the execute data describing the buffer
  311.      */
  312.     lpD3DExBuf->lpVtbl->Unlock(lpD3DExBuf);
  313.     memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA));
  314.     d3dExData.dwSize = sizeof(D3DEXECUTEDATA);
  315.     d3dExData.dwVertexCount = objData.num_vertices;
  316.     d3dExData.dwInstructionOffset = (ULONG)((char*)lpInsStart - (char*)lpBufStart);
  317.     d3dExData.dwInstructionLength = (ULONG)((char*)lpPointer - (char*)lpInsStart);
  318.     lpD3DExBuf->lpVtbl->SetExecuteData(lpD3DExBuf, &d3dExData);
  319.     /*
  320.      *  Create the light
  321.      */
  322.     memset(&light, 0, sizeof(D3DLIGHT));
  323.     light.dwSize = sizeof(D3DLIGHT);
  324.     light.dltType = D3DLIGHT_DIRECTIONAL;
  325.     light.dcvColor.r = D3DVAL(0.9);
  326.     light.dcvColor.g = D3DVAL(0.9);
  327.     light.dcvColor.b = D3DVAL(0.9);
  328.     light.dcvColor.a = D3DVAL(1.0);
  329.     light.dvDirection.x = D3DVALP(0.0, 12);
  330.     light.dvDirection.y = D3DVALP(0.0, 12);
  331.     light.dvDirection.z = D3DVALP(1.0, 12);
  332.     light.dvAttenuation0 = (float)1.0;
  333.     light.dvAttenuation1 = (float)0.0;
  334.     light.dvAttenuation2 = (float)0.0;
  335.     if (lpD3D->lpVtbl->CreateLight(lpD3D, &lpD3DLight, NULL) != D3D_OK)
  336.         return FALSE;
  337.     if (lpD3DLight->lpVtbl->SetLight(lpD3DLight, &light) != D3D_OK)
  338.         return FALSE;
  339.     if (lpView->lpVtbl->AddLight(lpView, lpD3DLight) != D3D_OK)
  340.         return FALSE;
  341.  
  342.     return TRUE;
  343. }
  344.  
  345.  
  346.