//Windows and DirectX code to run the LSystem object #include "LSystem.h" #include "cursorStack.h" #include "resource.h" #include #include #define HEIGHT 600 #define POPULATIONWIDTH 768 #define WIDTH 600 LPDIRECT3D8 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE8 g_pd3dDevice = NULL; // the rendering device LPD3DXMESH primitives[4]; LPDIRECTINPUT8 lpDI; // used to create input devices LPDIRECTINPUTDEVICE8 lpDIKeyboard; // keyboard device LPDIRECTINPUTDEVICE8 lpDIMouse; // mouse devise D3DVIEWPORT8 bigViewport; /* viewport for the main window */ HWND hwnd; /* handle for the main window */ HINSTANCE hInstance; /* handle of the instance of the app */ D3DXMATRIX lastMatrix; CursorStack cs; LSystem ls; /* Lindenmayer system */ int m_x,m_y; #define KEYDOWN(name, key) (name[key] & 0x80) /* macro for keyboard input*/ double zoom; /* zoom factor */ double rotationAroundY ; /* rotation around Y-axis for view, in degrees */ double altitude ; /* degrees about horizon for view */ double viewX; double viewY; bool pressed; /* bool to keep track if the left mouse button is pressed*/ HRESULT InitD3D(HWND hWnd ) { // Create the D3D object. if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ))) { MessageBox(hWnd,"Error in D3D Creation","Error",NULL); return E_FAIL; } // Get the current desktop display mode D3DDISPLAYMODE d3ddm; if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ))) { MessageBox(hWnd,"Error in Getting Display Mode","Error",NULL); return E_FAIL; } // Set up the structure used to create the D3DDevice D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.BackBufferFormat = d3ddm.Format; HRESULT hRet; // Create the D3DDevice if( FAILED( hRet = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ))) { if(hRet == D3DERR_OUTOFVIDEOMEMORY ) {MessageBox(hWnd,"D3DERR_OUTOFVIDEOMEMORY ","Error",NULL);} MessageBox(hWnd,"Error in Device Creation","Error",NULL); return E_FAIL; } // Turn off culling, so we see the front and back of the triangle g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); g_pd3dDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE ); // Turn on the zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); g_pd3dDevice->GetViewport(&bigViewport); // Device state would normally be set here return S_OK; } /* initializes the Lindenmayer System and cursor stack along with any * geometry used.*/ HRESULT InitObjects() { zoom=10; rotationAroundY =0; altitude =0; viewX = 0.0f; viewY = 0.0f; D3DXCreateCylinder(g_pd3dDevice,.1,.1,1,4,1,&primitives[0],NULL); ls.setInit("FfF"); ls.setIterations(2); ls.addRule('F',"F[YF][ZZYF][zzYF]"); ls.addRule('f',"F[YF][ZZYF][zzYF]"); D3DXMatrixIdentity(&lastMatrix); return S_OK; } // Cleans up D3D VOID Cleanup3D() { if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Cleans up Input bool CleanupInput() { if(lpDI) { if(lpDIKeyboard) { lpDIKeyboard->Acquire(); lpDIKeyboard -> Unacquire(); lpDIKeyboard->Release(); lpDIKeyboard = NULL; } /*if(lpDIMouse) { lpDIMouse->Acquire(); lpDIMouse -> Unacquire(); lpDIMouse->Release(); lpDIMouse = NULL; }*/ lpDI->Release(); lpDI=NULL; } return true; } // Initializes Dinput bool InitializeInput() { HRESULT hr; /* Create Dinput object */ hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8A , (void**)&lpDI, NULL); if(FAILED(hr)) { CleanupInput(); return false; } /* create Keyboard device */ hr = lpDI->CreateDevice(GUID_SysKeyboard, (struct IDirectInputDevice8A **)&lpDIKeyboard, NULL); if(FAILED(hr)) { CleanupInput(); return false; } /* set the data format for the keyboard */ hr = lpDIKeyboard->SetDataFormat(&c_dfDIKeyboard); if(FAILED(hr)) { CleanupInput(); return false; } /* set the cooperation level for the keyboard */ hr = lpDIKeyboard->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if(FAILED(hr)) { CleanupInput(); return false; } /* acquire the keyboard */ if (lpDIKeyboard) lpDIKeyboard->Acquire(); /* Create the mouse device */ hr = lpDI->CreateDevice(GUID_SysMouse ,&lpDIMouse, NULL); if(FAILED(hr)) { CleanupInput(); return false; } /* set the data format for the mouse */ hr = lpDIMouse->SetDataFormat(&c_dfDIMouse2 ); if(FAILED(hr)) { CleanupInput(); return false; } /* set the cooperationg level for the mouse */ hr = lpDIMouse->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if(FAILED(hr)) { CleanupInput(); return false; } /* acquire the mouse */ if (lpDIMouse) lpDIMouse->Acquire(); return true; } //Interprets keyboard and mouse input void InterpretInput() { BYTE diks[256]; HRESULT hRet; if (lpDIKeyboard) lpDIKeyboard->Acquire(); hRet = lpDIKeyboard->GetDeviceState(sizeof(diks),(LPVOID)&diks); /* keyboard interpretation*/ if(!FAILED(hRet)) { if(KEYDOWN(diks, DIK_ESCAPE))/* kill app */ { Cleanup3D(); CleanupInput(); PostQuitMessage (0) ; } else if(KEYDOWN(diks, DIK_EQUALS ) ) /* increase iterations */ { if(!pressed) { ls.iterations++; pressed = true; } } else if(KEYDOWN(diks,DIK_MINUS ) ) /* decrease iterations */ { if(!pressed) { ls.iterations--; if(ls.iterations < 1) ls.iterations = 0; pressed = true; } } else { pressed = false; } } DIMOUSESTATE2 mouseState; if (lpDIMouse) lpDIMouse->Acquire(); hRet = lpDIMouse->GetDeviceState(sizeof(mouseState),&mouseState); if(!FAILED(hRet)) { /*mouse logic to take care of rotation *around LSystem mesh and zooming*/ zoom -= mouseState.lZ / 50.0; if(zoom <1.0) zoom = 1.0; m_x += mouseState.lX; m_y += mouseState.lY; if(m_x < 0) m_x=0; if(m_x > bigViewport.Width-1) m_x = bigViewport.Width-1; if(m_y < 0) m_y=0; if(m_y > bigViewport.Height-1) m_y = bigViewport.Height-1; if(mouseState.rgbButtons[0]) { rotationAroundY = -mouseState.lX/2.0; altitude = -mouseState.lY/2.0; } } } /*Sets up the world, view, and projection transform matrices.*/ VOID SetupMatrices() { D3DXMATRIX matWorld; D3DXMatrixRotationY( &matWorld, timeGetTime()/150.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); D3DXMATRIX matView; D3DXMATRIX temp; /* rotates world coordinates from mouse rotation */ D3DXMatrixMultiply(&lastMatrix, &lastMatrix, D3DXMatrixRotationY(&temp, D3DXToRadian(rotationAroundY))); D3DXMatrixMultiply(&lastMatrix, &lastMatrix, D3DXMatrixRotationX(&temp, D3DXToRadian(altitude))); D3DXMatrixMultiply(&lastMatrix, &lastMatrix, D3DXMatrixTranslation(&temp, -viewX, -viewY, 0) ); D3DXMatrixMultiply(&matView, &lastMatrix, D3DXMatrixTranslation(&temp, 0, 0, zoom) ); /* set initial rotation values */ rotationAroundY = 0.0f; altitude = 0.0f; viewX = 0.0f; viewY = 0.0f; g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView); /* Get projection matrix */ D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 200.0f ); /* set projection matrix */ g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } /* Sets up materials and lights for D3D */ VOID SetupLights() { // Set up a material. D3DMATERIAL8 mtrl; ZeroMemory( &mtrl, sizeof(D3DMATERIAL8) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; mtrl.Specular.r = mtrl.Specular.b = mtrl.Specular.g = mtrl.Specular.a = 1.0f; g_pd3dDevice->SetMaterial( &mtrl ); /* Set up 3 lights for even lighting */ D3DXVECTOR3 vecDir,v2,v3; D3DLIGHT8 light, l2, l3; ZeroMemory( &light, sizeof(D3DLIGHT8) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = light.Specular.r =1.0f; light.Diffuse.g = light.Specular.g =1.0f; light.Diffuse.b = light.Specular.b =1.0f; vecDir = D3DXVECTOR3(-1.0f, -1.0f, 1.0f ); D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); light.Range = 1000.0f; g_pd3dDevice->SetLight( 0, &light ); g_pd3dDevice->LightEnable( 0, TRUE ); ZeroMemory( &l2, sizeof(D3DLIGHT8) ); l2.Type = D3DLIGHT_DIRECTIONAL; l2.Diffuse.r = l2.Specular.r =0.5f; l2.Diffuse.g = l2.Specular.g =0.5f; l2.Diffuse.b = l2.Specular.b =0.5f; v2 = D3DXVECTOR3(1.0f, 0.0f, 0.0f ); D3DXVec3Normalize( (D3DXVECTOR3*)&l2.Direction, &v2 ); l2.Range = 1000.0f; g_pd3dDevice->SetLight( 1, &l2 ); g_pd3dDevice->LightEnable( 1, TRUE ); ZeroMemory( &l3, sizeof(D3DLIGHT8) ); l3.Type = D3DLIGHT_DIRECTIONAL; l3.Diffuse.r = l3.Specular.r =0.25f; l3.Diffuse.g = l3.Specular.g =0.25f; l3.Diffuse.b = l3.Specular.b =0.25f; v3 = D3DXVECTOR3(0.0f, 1.0f, -0.5f ); D3DXVec3Normalize( (D3DXVECTOR3*)&l3.Direction, &v3 ); l3.Range = 1000.0f; g_pd3dDevice->SetLight( 2, &l3 ); g_pd3dDevice->LightEnable( 2, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00002040 ); } //Procedure method for the Dialog box that defines the LSystem BOOL CALLBACK DefineDlgProc (HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) { char angle[256]; char newRules[256]; switch (iMsg) { case WM_INITDIALOG: SetDlgItemText(hDlg,LSYS_RULES,ls.getRulesString().c_str()); SetDlgItemText(hDlg,LSYS_INITIAL,ls.init.c_str()); SetDlgItemInt(hDlg,LSYS_ITERATIONS,ls.iterations,TRUE); sprintf(angle,"%3.3f",cs.angle); SetDlgItemText(hDlg,LSYS_ANGLE,angle); return TRUE; case WM_COMMAND : switch (LOWORD (wParam)) { case IDOK : case IDCANCEL : ls.init.resize(80); GetDlgItemText(hDlg,LSYS_INITIAL,(char*)ls.init.c_str(),80); GetDlgItemText(hDlg,LSYS_RULES,newRules,300); ls.setRules(newRules); GetDlgItemText(hDlg,LSYS_ANGLE,angle,10); cs.angle = atof(angle); ls.iterations = GetDlgItemInt(hDlg,LSYS_ITERATIONS,NULL,TRUE); EndDialog (hDlg, 0) ; return TRUE ; } break ; } return FALSE; } /*The window's message handler */ LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { HMENU hMenu; switch( msg ) { case WM_COMMAND: hMenu = GetMenu (hwnd); switch(LOWORD(wParam)) { case LSYS_DEFINE: DialogBox (hInstance, "DEFINELSYSTEM", hwnd,DefineDlgProc) ; return 0; case LSYS_EXIT: SendMessage (hwnd, WM_CLOSE, 0, 0L); return 0; } return 0; case WM_DESTROY: PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } /* Draws the screen */ VOID Render() { if( NULL == g_pd3dDevice ) return; g_pd3dDevice->SetViewport(&bigViewport); g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); // Begin the scene g_pd3dDevice->BeginScene(); SetupMatrices(); SetupLights(); /* use cursorstack to draw L-System */ cs.interpretString(ls.output()); D3DXMatrixIdentity(&cs.vect[0].matrix); g_pd3dDevice->EndScene(); // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { // Register the window class WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, "LSYSTEM", "LSystems", NULL }; RegisterClassEx( &wc ); // Create the application's window HWND hWnd = CreateWindow( "LSystems", "LSystems", WS_OVERLAPPEDWINDOW, 100, 100, WIDTH, HEIGHT, GetDesktopWindow(), NULL, wc.hInstance, NULL ); cs= CursorStack(); hwnd = hWnd; HRESULT hRet; hInstance = hInst; // Initialize Direct3D hRet = InitD3D( hWnd ) ; if(!InitializeInput()) {MessageBox(hwnd,"error","error",NULL);} hRet= InitObjects() ; // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); cs.setDevice(g_pd3dDevice); cs.vect[0].mesh = &primitives[0]; // Enter the message loop MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { InterpretInput(); Render(); } } // Clean up everything and exit the app Cleanup3D(); UnregisterClass( "D3D Tutorial", wc.hInstance ); return 0; }