1 // =============================================================
    2 // Sean Smith
    3 // Main.cpp
    4 // =============================================================
    5 
    6 // include the basic windows header files and the Direct3D header file
    7 #include <windows.h>
    8 #include <windowsx.h>
    9 #include <d3d9.h>
   10 #include <d3dx9.h>
   11 #include <vector>
   12 #include <time.h>
   13 #include <math.h>
   14 #include <sstream>
   15 using namespace std;
   16 
   17 // define the screen resolution and keyboard macros
   18 #define SCREEN_WIDTH 1024
   19 #define SCREEN_HEIGHT 768
   20 #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
   21 #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
   22 
   23 // include the Direct3D Library files
   24 #pragma comment (lib, "d3d9.lib")
   25 #pragma comment (lib, "d3dx9.lib")
   26 
   27 // global declarations
   28 LPDIRECT3D9 d3d;    // the pointer to our Direct3D interface
   29 LPDIRECT3DDEVICE9 d3ddev;    // the pointer to the device class
   30 
   31 // object variables
   32 int numObjects = 5000;
   33 float innerRadius = 3;
   34 float outerRadius = 5;
   35 int sides = 10;
   36 int rings = 10;
   37 
   38 // variables for benchmark
   39 int startTime = 0, counter = 0, framerate = 0;
   40 
   41 // color definitions
   42 const D3DXCOLOR BLACK = D3DXCOLOR(0.0, 0.0, 0.0, 1.0);
   43 const D3DXCOLOR WHITE = D3DXCOLOR(1.0, 1.0, 1.0, 1.0);
   44 const D3DXCOLOR BLUE = D3DXCOLOR(0.0, 0.0, 1.0, 1.0);
   45 const D3DXCOLOR GREEN = D3DXCOLOR(0.0, 1.0, 0.0, 1.0);
   46 const D3DXCOLOR RED = D3DXCOLOR(1.0, 0.0, 0.0, 1.0);
   47 const D3DXCOLOR CYAN = D3DXCOLOR(0.0, 1.0, 1.0, 1.0);
   48 const D3DXCOLOR PURPLE = D3DXCOLOR(1.0, 0.0, 1.0, 1.0);
   49 
   50 // function prototypes
   51 void initD3D(HWND hWnd);    // sets up and initializes Direct3D
   52 void render_frame(void);    // renders a single frame
   53 void cleanD3D(void);        // closes Direct3D and releases memory
   54 void init_graphics(void);   // 3D declarations
   55 struct Torus;            // mesh struct
   56 void init_Torus();        //
   57 
   58 // mesh declarations
   59 LPD3DXMESH meshTorus;    // define the mesh pointer
   60 LPD3DXEFFECT shaderEffect1;
   61 vector<Torus> torusVector;
   62 
   63 // sprite declaration
   64 //ID3DXSprite ID3DXSprite;
   65 LPD3DXSPRITE textSprite;
   66 ID3DXFont *font = NULL;
   67 
   68 // the WindowProc function prototype
   69 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
   70 
   71 // mesh object struct
   72 struct Torus
   73 {
   74     D3DXMATRIX pos;
   75     D3DXMATRIX rotY;
   76     D3DXCOLOR color;
   77 };
   78 
   79 //initialization
   80 //describe an Arial 32-point font
   81 D3DXFONT_DESC desc = {
   82     32, //height
   83     0, //width
   84     0, //escapement
   85     0, //orientation
   86     0, //weight
   87     false, //italic
   88     false, //underline
   89     false, //strikeout
   90     DEFAULT_CHARSET, //character set
   91     OUT_TT_PRECIS, //precision
   92     CLIP_DEFAULT_PRECIS, //clipping
   93     DEFAULT_QUALITY, //quality
   94     DEFAULT_PITCH, //pitch and family
   95     "Arial" //font name
   96 };
   97 
   98 
   99 
  100 // the entry point for any Windows program
  101 int WINAPI WinMain(HINSTANCE hInstance,
  102                    HINSTANCE hPrevInstance,
  103                    LPSTR lpCmdLine,
  104                    int nCmdShow)
  105 {
  106     HWND hWnd;
  107     WNDCLASSEX wc;
  108 
  109     ZeroMemory(&wc, sizeof(WNDCLASSEX));
  110 
  111     wc.cbSize = sizeof(WNDCLASSEX);
  112     wc.style = CS_HREDRAW | CS_VREDRAW;
  113     wc.lpfnWndProc = (WNDPROC)WindowProc;
  114     wc.hInstance = hInstance;
  115     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  116     wc.lpszClassName = "WindowClass";
  117 
  118     RegisterClassEx(&wc);
  119 
  120     hWnd = CreateWindowEx(NULL, "WindowClass", "D3DX Vertext and Pixel Shader 2",
  121                           WS_OVERLAPPEDWINDOW, 300, 300, SCREEN_WIDTH, SCREEN_HEIGHT,
  122                           NULL, NULL, hInstance, NULL);
  123 
  124     ShowWindow(hWnd, nCmdShow);
  125 
  126     // set up and initialize Direct3D
  127     initD3D(hWnd);
  128 
  129     // enter the main loop:
  130 
  131     MSG msg;
  132 
  133     while(TRUE)
  134     {
  135         DWORD starting_point = GetTickCount();
  136 
  137         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  138         {
  139             if (msg.message == WM_QUIT)
  140                 break;
  141 
  142             TranslateMessage(&msg);
  143             DispatchMessage(&msg);
  144         }
  145 
  146         render_frame();
  147 
  148         // check the 'escape' key
  149         if(KEY_DOWN(VK_ESCAPE))
  150             PostMessage(hWnd, WM_DESTROY, 0, 0);
  151 
  152         while ((GetTickCount() - starting_point) < 25);
  153     }
  154 
  155     // clean up DirectX and COM
  156     cleanD3D();
  157 
  158     return msg.wParam;
  159 }
  160 
  161 
  162 // this is the main message handler for the program
  163 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  164 {
  165     switch(message)
  166     {
  167         case WM_DESTROY:
  168             {
  169                 PostQuitMessage(0);
  170                 return 0;
  171             } break;
  172     }
  173 
  174     return DefWindowProc (hWnd, message, wParam, lParam);
  175 }
  176 
  177 
  178 // this function initializes and prepares Direct3D for use
  179 void initD3D(HWND hWnd)
  180 {
  181     d3d = Direct3DCreate9(D3D_SDK_VERSION);
  182 
  183     D3DPRESENT_PARAMETERS d3dpp;
  184 
  185     ZeroMemory(&d3dpp, sizeof(d3dpp));
  186     d3dpp.Windowed = TRUE;
  187     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  188     d3dpp.hDeviceWindow = hWnd;
  189     d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
  190     d3dpp.BackBufferWidth = SCREEN_WIDTH;
  191     d3dpp.BackBufferHeight = SCREEN_HEIGHT;
  192     d3dpp.EnableAutoDepthStencil = TRUE;
  193     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  194 
  195     // create a device class using this information and the info from the d3dpp stuct
  196     d3d->CreateDevice(D3DADAPTER_DEFAULT,
  197                       D3DDEVTYPE_HAL,
  198                       hWnd,
  199                       D3DCREATE_HARDWARE_VERTEXPROCESSING,
  200                       &d3dpp,
  201                       &d3ddev);
  202 
  203     srand(time(NULL));
  204     init_graphics();    // initialize graphics
  205     init_Torus();        // initialize torus object
  206 
  207     return;
  208 }
  209 
  210 
  211 // this is the function used to render a single frame
  212 void render_frame(void)
  213 {
  214     d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
  215     d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
  216 
  217     d3ddev->BeginScene();
  218 
  219     counter++; 
  220     if (GetTickCount() > startTime + 1000)
  221     {
  222         framerate = counter;
  223         counter = 0;
  224         startTime = GetTickCount();
  225     }
  226 
  227     // begin drawing the text sprite
  228     textSprite->Begin(D3DXSPRITE_ALPHABLEND);
  229 
  230     RECT rect = {20, 20, SCREEN_WIDTH, SCREEN_HEIGHT};
  231     D3DCOLOR color = D3DCOLOR_XRGB(0,255,0);
  232 
  233     string fps = "";
  234     static char string[256];
  235     int vertObject = meshTorus->GetNumVertices();
  236     int faceObject = meshTorus->GetNumFaces();
  237     sprintf(string, "FPS: %d\n"
  238         "Vertices per Object: %d\n"
  239         "Faces per Object: %d\n"
  240         "Total Verticies: %d\n"
  241         "Total Faces: %d\n"
  242         "Total Objects: %d\n", 
  243         framerate, 
  244         vertObject, 
  245         faceObject, 
  246         vertObject * numObjects, 
  247         faceObject * numObjects, 
  248         numObjects);
  249     font->DrawText(textSprite, string, -1, &rect, DT_NOCLIP, color);
  250 
  251     // set the view transform
  252     D3DXMATRIX matView;    // the view transform matrix
  253     D3DXMatrixLookAtLH(&matView,
  254     &D3DXVECTOR3 (0.0f, 3.0f, 250.0f),    // the camera position
  255     &D3DXVECTOR3 (0.0f, 0.0f, 0.0f),      // the look-at position
  256     &D3DXVECTOR3 (0.0f, 1.0f, 0.0f));    // the up direction
  257 
  258       // set the projection transform
  259     D3DXMATRIX matProjection;    // the projection transform matrix
  260     D3DXMatrixPerspectiveFovLH(&matProjection,
  261                                D3DXToRadian(45),    // the horizontal field of view
  262                                (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
  263                                1.0f,    // the near view-plane
  264                                2000.0f);    // the far view-plane
  265 
  266     //set the ambient/diffuse light source vector
  267     D3DXVECTOR3 mLightVecW  = D3DXVECTOR3(0.0, 1.0f, 1.0f);
  268 
  269     //set the ambient/diffuse colors
  270     float ambLevel = 0.1f;
  271     float difLevel = 0.7f;
  272     D3DXCOLOR mDiffuseLight = D3DXCOLOR(difLevel, difLevel, difLevel, 1.0f);
  273     D3DXCOLOR mAmbientMtrl  = WHITE;
  274     D3DXCOLOR mAmbientLight = D3DXCOLOR(ambLevel, ambLevel, ambLevel, 1.0f);
  275 
  276     //pass variables to shader
  277     shaderEffect1->SetValue("gLightVecW", &mLightVecW, sizeof(D3DXVECTOR3));
  278     shaderEffect1->SetValue("gDiffuseLight", &mDiffuseLight, sizeof(D3DXCOLOR));
  279     shaderEffect1->SetValue("gAmbientMtrl", &mAmbientMtrl, sizeof(D3DXCOLOR));
  280     shaderEffect1->SetValue("gAmbientLight", &mAmbientLight, sizeof(D3DXCOLOR));
  281 
  282     shaderEffect1->SetMatrix("mView", &(matView));
  283     shaderEffect1->SetMatrix("mProjection", &(matProjection));
  284 
  285     static float index = 0.0f; index += 0.05f;
  286 
  287 /**
  288  ** RENDERING ALL OF THE OBJECTS
  289  **/
  290     vector<Torus>::iterator vecIterator;
  291 
  292     for (vecIterator = torusVector.begin(); vecIterator != torusVector.end(); vecIterator++)
  293     {
  294         Torus t = *vecIterator;
  295 
  296         D3DXMatrixRotationYawPitchRoll( &t.rotY, 0, 0, -index);
  297 
  298         //calculate lighting normal based on current transforms
  299         D3DXMATRIX worldInverseTranspose;
  300         D3DXMatrixInverse(&worldInverseTranspose, 0, &(t.rotY * t.pos));
  301         D3DXMatrixTranspose(&worldInverseTranspose, &worldInverseTranspose);
  302 
  303         //send data to the shader
  304         shaderEffect1->SetMatrix("mRotation", &(t.rotY));
  305         shaderEffect1->SetMatrix("mTranslation", &(t.pos));
  306         shaderEffect1->SetMatrix("gWorldInverseTranspose", &worldInverseTranspose);
  307         shaderEffect1->SetValue("gDiffuseMtrl", &(t.color), sizeof(D3DXCOLOR));
  308 
  309         UINT numPasses = 0;
  310         shaderEffect1->Begin(&numPasses, 0);
  311 
  312         for (int i=0; i<numPasses; ++i)
  313         {
  314             shaderEffect1->BeginPass(i);
  315             meshTorus->DrawSubset(0);
  316             shaderEffect1->EndPass();
  317         }    
  318 
  319         shaderEffect1->End();
  320     }
  321 /**
  322  ** RENDERING OBJECTS END
  323  **/
  324 
  325     textSprite->End();
  326 
  327     d3ddev->EndScene(); 
  328 
  329     d3ddev->Present(NULL, NULL, NULL, NULL);
  330 
  331     return;
  332 }
  333 
  334 
  335 // this is the function that cleans up Direct3D and COM
  336 void cleanD3D(void)
  337 {
  338     font->Release();
  339     shaderEffect1->Release();
  340     meshTorus->Release();    // close and release the teapot mesh
  341     d3ddev->Release();    // close and release the 3D device
  342     d3d->Release();    // close and release Direct3D
  343 
  344     return;
  345 }
  346 
  347 
  348 // this is the function that puts the 3D models into video RAM
  349 void init_graphics(void)
  350 {
  351     D3DXCreateSprite(d3ddev, &textSprite);
  352 
  353     //create the font object
  354     D3DXCreateFontIndirect(d3ddev, &desc, &font);
  355 
  356     D3DXCreateTorus(d3ddev, innerRadius, outerRadius, sides, rings, &meshTorus, NULL);
  357     ID3DXBuffer *errors = 0;
  358 
  359     D3DXCreateEffectFromFile(d3ddev, "ProgrammableShader.fx", NULL, NULL, 0, NULL, &shaderEffect1, &errors);
  360     if (errors )
  361         MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);
  362 
  363     shaderEffect1->SetTechnique("technique1");
  364 
  365     return;
  366 }
  367 
  368 void init_Torus()
  369 {
  370     int iRandColor;
  371 
  372     // Create all torus objects
  373     for (int i = 0; i < numObjects; i++)
  374     {
  375         Torus torusObject;
  376 
  377         // Apply movement function
  378         D3DXMatrixTranslation(&torusObject.pos, 
  379             (((float)i * 2) * cos(6 * (float)i)), (((float)i * 2) * sin(6 * (float)i)), -(i * 4));
  380 
  381         // Get random color
  382         iRandColor = rand() % 6 + 1;
  383         if (iRandColor == 1)
  384             torusObject.color = WHITE;
  385         else if (iRandColor == 2)
  386             torusObject.color = BLUE;
  387         else if (iRandColor == 3)
  388             torusObject.color = GREEN;
  389         else if (iRandColor == 4)
  390             torusObject.color = RED;
  391         else if (iRandColor == 5)
  392             torusObject.color = CYAN;
  393         else if (iRandColor == 6)
  394             torusObject.color = PURPLE;
  395 
  396         // Add object
  397         torusVector.push_back(torusObject);
  398     }
  399 }