![]() |
![]() ![]() Direct3D Retained Mode Sample// File: hello.cpp // Simple Direct3D Retained-Mode example // Must precede other defines and includes #define INITGUID #include <windows.h> #include <malloc.h> #include <d3drmwin.h> #define MAXDRV 5 // Maximum D3D drivers expected // Global variables LPDIRECT3DRM lpD3DRM; // Direct3DRM object // DirectDrawClipper object LPDIRECTDRAWCLIPPER lpDDClipper; struct _gInfo { LPDIRECT3DRMDEVICE dev; // Direct3DRM device LPDIRECT3DRMVIEWPORT view; // Direct3DRM viewport through which // scene is viewed LPDIRECT3DRMFRAME scene; // Master frame LPDIRECT3DRMFRAME camera; // Frame describing user's POV GUID drvGUID[MAXDRV]; // GUIDs of available D3D drivers char drvName[MAXDRV][50]; // Names of available D3D drivers int numDrv; // available D3D drivers int curr; // D3D driver currently used BOOL bQuit; // Program is about to terminate BOOL bInit; // All D3DRM objects are initialized BOOL bMin; // Window is minimized int bpp; // Bit depth of current display mode } gInfo; // Function prototypes. BOOL InitApp(HINSTANCE, int); long FAR PASCAL WindowProc(HWND, UINT, WPARAM, LPARAM); BOOL EnumDrivers(HWND win); HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDevDesc, LPSTR lpDevName, LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext); DWORD bppToDDBD(int bpp); BOOL CreateDevAndView(LPDIRECTDRAWCLIPPER lpDDClipper, int driver, int width, int height); BOOL SetRenderState(void); BOOL RenderLoop(void); BOOL MyScene(LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view, LPDIRECT3DRMFRAME scene, LPDIRECT3DRMFRAME camera); void MakeMyFrames(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME *lplpLtFr1, LPDIRECT3DRMFRAME *lplpWorldF); void MakeMyLights(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME lpLtFr1, LPDIRECT3DRMLIGHT *lplpLt1, LPDIRECT3DRMLIGHT *lplpLt2); void SetMyPositions(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME lpLtFr1, LPDIRECT3DRMFRAME lpWorldF); void MakeMyMesh(LPDIRECT3DRMMESHBUILDER *lplpMesh); void MakeMyWrap(LPDIRECT3DRMMESHBUILDER mesh, LPDIRECT3DRMWRAP *lpWrap); void AddMyTexture(LPDIRECT3DRMMESHBUILDER lpMesh, LPDIRECT3DRMTEXTURE *lplpTex); void CleanUp(void); // Initializes the application and enters a message loop. // Message loop renders scene until quit message is received. int PASCAL WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdline, int cmdshow) { MSG msg; HACCEL accel = NULL; int failcount = 0; // Number of times RenderLoop has failed hPrevInst; cmdline; if ( !InitApp(hInst, cmdshow) ) return 1; while ( !gInfo.bQuit ) { while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (!TranslateAccelerator(msg.hwnd, accel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // If app is not minimized, not about to quit, and D3DRM // has been initialized, begin rendering. if ( !gInfo.bMin && !gInfo.bQuit && gInfo.bInit ) { if ( !RenderLoop() ) ++failcount; if (failcount > 2) { CleanUp(); break; } } } return msg.wParam; } // Creates window and initializes all objects necessary to begin // rendering. BOOL InitApp(HINSTANCE hInst, int cmdshow) { HWND win; HDC hdc; WNDCLASS wc; RECT rc; // Set up and register the window class. wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(DWORD); wc.hInstance = hInst; wc.hIcon = LoadIcon(hInst, "AppIcon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "D3DRM Example"; if (!RegisterClass(&wc)) return FALSE; // Initialize the global variables. memset(&gInfo, 0, sizeof(gInfo)); // Create the window. win = CreateWindow("D3DRM Example", "Hello World (Direct3DRM)", WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 500, 500, NULL, NULL, hInst, NULL); if ( !win ) return FALSE; // Record the current display bits-per-pixel. hdc = GetDC(win); gInfo.bpp = GetDeviceCaps(hdc, BITSPIXEL); ReleaseDC(win, hdc); // Enumerate the D3D drivers and select one. if ( !EnumDrivers(win) ) return FALSE; // Create the D3DRM object and the D3DRM window object. lpD3DRM = NULL; Direct3DRMCreate(&lpD3DRM); // Create the master scene frame and camera frame. lpD3DRM->CreateFrame(NULL, &gInfo.scene); lpD3DRM->CreateFrame(gInfo.scene, &gInfo.camera); gInfo.camera->SetPosition(gInfo.scene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0)); // Create a DirectDrawClipper object and associate the // window with it. DirectDrawCreateClipper(0, &lpDDClipper, NULL); lpDDClipper->SetHWnd(0, win); // Create the D3DRM device by using the selected D3D driver. GetClientRect(win, &rc); CreateDevAndView(lpDDClipper, gInfo.curr, rc.right, rc.bottom); // Create the scene to be rendered. MyScene(gInfo.dev, gInfo.view, gInfo.scene, gInfo.camera); gInfo.bInit = TRUE; // Initialization completed // Display the window. ShowWindow(win, cmdshow); UpdateWindow(win); return TRUE; } // Main window message handler. LONG FAR PASCAL WindowProc(HWND win, UINT msg, WPARAM wparam, LPARAM lparam) { RECT r; PAINTSTRUCT ps; LPDIRECT3DRMWINDEVICE lpD3DRMWinDev; switch (msg) { case WM_DESTROY: CleanUp(); break; case WM_ACTIVATE: { // Create a Windows-specific D3DRM window device to handle this // message. LPDIRECT3DRMWINDEVICE lpD3DRMWinDev; if (!gInfo.dev) break; gInfo.dev->QueryInterface(IID_IDirect3DRMWinDevice, (void **) &lpD3DRMWinDev); lpD3DRMWinDev->HandleActivate((WORD) wparam); lpD3DRMWinDev->Release(); } break; case WM_PAINT: if (!gInfo.bInit || !gInfo.dev) return DefWindowProc(win, msg, wparam, lparam); // Create a Windows-specific D3DRM window device to handle this // message. if (GetUpdateRect(win, &r, FALSE)) { BeginPaint(win, &ps); gInfo.dev->QueryInterface(IID_IDirect3DRMWinDevice, (void **) &lpD3DRMWinDev); if (FAILED(lpD3DRMWinDev->HandlePaint(ps.hdc))) lpD3DRMWinDev->Release(); EndPaint(win, &ps); } break; default: return DefWindowProc(win, msg, wparam, lparam); } return 0L; } // Enumerate the available D3D drivers and choose one. BOOL EnumDrivers(HWND win) { LPDIRECTDRAW lpDD; LPDIRECT3D lpD3D; HRESULT rval; // Create a DirectDraw object and query for the Direct3D interface // to use to enumerate the drivers. DirectDrawCreate(NULL, &lpDD, NULL); rval = lpDD->QueryInterface(IID_IDirect3D, (void**) &lpD3D); if (rval != DD_OK) { lpDD->Release(); return FALSE; } // Enumerate the drivers, setting curr to -1 to initialize the // driver selection code in enumDeviceFunc. gInfo.curr = -1; lpD3D->EnumDevices(enumDeviceFunc, &gInfo.curr); // Ensure at least one valid driver was found. if (gInfo.numDrv == 0) return FALSE; lpD3D->Release(); lpDD->Release(); return TRUE; } // Callback function that records each usable D3D driver's name // and GUID. Chooses a driver and sets *lpContext to this driver. HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDevDesc, LPSTR lpDevName, LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext) { static BOOL hardware = FALSE; // Current start driver is hardware static BOOL mono = FALSE; // Current start driver is mono light LPD3DDEVICEDESC lpDesc; int *lpStartDriver = (int *)lpContext; // Decide which device description should be consulted. lpDesc = lpHWDesc->dcmColorModel ? lpHWDesc : lpHELDesc; // If this driver cannot render in the current display bit-depth, // skip it and continue with the enumeration. if (!(lpDesc->dwDeviceRenderBitDepth & bppToDDBD(gInfo.BPP))) return D3DENUMRET_OK; // Record this driver's name and GUID. memcpy(&gInfo.drvGUID[gInfo.numDrv], lpGuid, sizeof(GUID)); lstrcpy(&gInfo.drvName[gInfo.numDrv][0], lpDevName); // Choose hardware over software, RGB lights over mono lights. if (*lpStartDriver == -1) { // This is the first valid driver. *lpStartDriver = gInfo.numDrv; hardware = lpDesc == lpHWDesc ? TRUE : FALSE; mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE; } else if (lpDesc == lpHWDesc && !hardware) { // This driver is hardware and the start driver is not. *lpStartDriver = gInfo.numDrv; hardware = lpDesc == lpHWDesc ? TRUE : FALSE; mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE; } else if ((lpDesc == lpHWDesc && hardware ) || (lpDesc == lpHELDesc && !hardware)) { if (lpDesc->dcmColorModel == D3DCOLOR_MONO && !mono) { // This driver and the start driver are the same type, and // this driver is mono whereas the start driver is not. *lpStartDriver = gInfo.numDrv; hardware = lpDesc == lpHWDesc ? TRUE : FALSE; mono = lpDesc->dcmColorModel & D3DCOLOR_MONO ? TRUE : FALSE; } } gInfo.numDrv++; if (gInfo.numDrv == MAXDRV) return (D3DENUMRET_CANCEL); return (D3DENUMRET_OK); } // Converts bits-per-pixel to a DirectDraw bit-depth flag. DWORD bppToDDBD(int bpp) { switch(bpp) { case 1: return DDBD_1; case 2: return DDBD_2; case 4: return DDBD_4; case 8: return DDBD_8; case 16: return DDBD_16; case 24: return DDBD_24; case 32: return DDBD_32; default: return 0; } } // Create the D3DRM device and viewport with the given D3D driver and // with the specified size. BOOL CreateDevAndView(LPDIRECTDRAWCLIPPER lpDDClipper, int driver, int width, int height) { HRESULT rval; // Create the D3DRM device from this window by using the specified // D3D driver. lpD3DRM->CreateDeviceFromClipper(lpDDClipper, &gInfo.drvGUID[driver], width, height, &gInfo.dev); // Create the D3DRM viewport by using the camera frame. Set the // background depth to a large number. The width and height // might have been slightly adjusted, so get them from the device. width = gInfo.dev->GetWidth(); height = gInfo.dev->GetHeight(); rval = lpD3DRM->CreateViewport(gInfo.dev, gInfo.camera, 0, 0, width, height, &gInfo.view); if (rval != D3DRM_OK) { gInfo.dev->Release(); return FALSE; } rval = gInfo.view->SetBack(D3DVAL(5000.0)); if (rval != D3DRM_OK) { gInfo.dev->Release(); gInfo.view->Release(); return FALSE; } // Set the render quality, fill mode, lighting state, // and color shade info. if (!SetRenderState()) return FALSE; return TRUE; } // Set the render quality and shade information. BOOL SetRenderState(void) { HRESULT rval; // Set the render quality (light toggle, fill mode, shade mode). rval = gInfo.dev->SetQuality(D3DRMLIGHT_ON | D3DRMFILL_SOLID | D3DRMSHADE_GOURAUD); if (rval != D3DRM_OK) return FALSE; switch (gInfo.bpp) { case 1: if (FAILED(gInfo.dev->SetShades(4))) goto shades_error; if (FAILED(lpD3DRM->SetDefaultTextureShades(4))) goto shades_error; break; case 16: if (FAILED(gInfo.dev->SetShades(32))) goto shades_error; if (FAILED(lpD3DRM->SetDefaultTextureColors(64))) goto shades_error; if (FAILED(lpD3DRM->SetDefaultTextureShades(32))) goto shades_error; break; case 24: case 32: if (FAILED(gInfo.dev->SetShades(256))) goto shades_error; if (FAILED(lpD3DRM->SetDefaultTextureColors(64))) goto shades_error; if (FAILED(lpD3DRM->SetDefaultTextureShades(256))) goto shades_error; break; } return TRUE; shades_error: return FALSE; } // Clear the viewport, render the next frame, and update the window. BOOL RenderLoop() { HRESULT rval; // Tick the scene. rval = gInfo.scene->Move(D3DVAL(1.0)); if (rval != D3DRM_OK) return FALSE; // Clear the viewport. rval = gInfo.view->Clear(); if (rval != D3DRM_OK) return FALSE; // Render the scene to the viewport. rval = gInfo.view->Render(gInfo.scene); if (rval != D3DRM_OK) return FALSE; // Update the window. rval = gInfo.dev->Update(); if (rval != D3DRM_OK) return FALSE; return TRUE; } // Calls the functions that create the frames, lights, mesh, and // texture. Releases all interfaces on completion. BOOL MyScene(LPDIRECT3DRMDEVICE dev, LPDIRECT3DRMVIEWPORT view, LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam) { LPDIRECT3DRMFRAME lpLtframe1, lpWorldF; LPDIRECT3DRMLIGHT lpLt1, lpLt2; LPDIRECT3DRMTEXTURE lpTex; LPDIRECT3DRMWRAP lpWrap; LPDIRECT3DRMMESHBUILDER lpMesh; lpLtframe1 = lpWorldF = NULL; lpLt1 = lpLt2 = NULL; lpTex = NULL; lpWrap = NULL; lpMesh = NULL; MakeMyFrames(lpScene, lpCam, &lpLtframe1, &lpWorldF); MakeMyLights(lpScene, lpCam, lpLtframe1, &lpLt1, &lpLt2); SetMyPositions(lpScene, lpCam, lpLtframe1, lpWorldF); MakeMyMesh(&lpMesh); MakeMyWrap(lpMesh, &lpWrap); AddMyTexture(lpMesh, &lpTex); // Now that the visual object has been created, add it // to the world frame. lpWorldF->AddVisual((LPDIRECT3DRMVISUAL) lpMesh); lpLtframe1->Release(); lpWorldF->Release(); lpMesh->Release(); lpLt1->Release(); lpLt2->Release(); lpTex->Release(); lpWrap->Release(); return TRUE; } // Create frames used in the scene. void MakeMyFrames(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME * lplpLtFr1, LPDIRECT3DRMFRAME * lplpWorldF) { lpD3DRM->CreateFrame(lpScene, lplpLtFr1); lpD3DRM->CreateFrame(lpScene, lplpWorldF); } // MakeMyLights // Create lights used in the scene. void MakeMyLights(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME lpLtFr1, LPDIRECT3DRMLIGHT * lplpLt1, LPDIRECT3DRMLIGHT * lplpLt2) { lpD3DRM->CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, D3DVAL(0.9), D3DVAL(0.9), D3DVAL(0.9), lplpLt1); lpLtFr1->AddLight(*lplpLt1); lpD3DRM->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1), D3DVAL(0.1), D3DVAL(0.1), lplpLt2); lpScene->AddLight(*lplpLt2); } // Set the positions and orientations of the light, camera, and // world frames. Establish a rotation for the globe. void SetMyPositions(LPDIRECT3DRMFRAME lpScene, LPDIRECT3DRMFRAME lpCam, LPDIRECT3DRMFRAME lpLtFr1, LPDIRECT3DRMFRAME lpWorldF) { lpLtFr1->SetPosition(lpScene, D3DVAL(2), D3DVAL(0.0), D3DVAL(22)); lpCam->SetPosition(lpScene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0)); lpCam->SetOrientation(lpScene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0)); lpWorldF->SetPosition(lpScene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(15)); lpWorldF->SetOrientation(lpScene, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0), D3DVAL(1), D3DVAL(0.0)); lpWorldF->SetRotation(lpScene, D3DVAL(0.0), D3DVAL(0.1), D3DVAL(0.0), D3DVAL(0.05)); } // Create MeshBuilder object, load, scale, and color the mesh. void MakeMyMesh(LPDIRECT3DRMMESHBUILDER * lplpMesh) { lpD3DRM->CreateMeshBuilder(lplpMesh); (*lplpMesh)->Load("sphere4.x", NULL, D3DRMLOAD_FROMFILE, NULL, NULL); (*lplpMesh)->Scale(D3DVAL(2), D3DVAL(2), D3DVAL(2)); // Set sphere to white to avoid unexpected texture-blending results. (*lplpMesh)->SetColorRGB(D3DVAL(1), D3DVAL(1), D3DVAL(1)); } // Creates and applies wrap for texture. void MakeMyWrap(LPDIRECT3DRMMESHBUILDER mesh, LPDIRECT3DRMWRAP * lpWrap) { D3DVALUE miny, maxy, height; D3DRMBOX box; mesh->GetBox(&box); maxy = box.max.y; miny = box.min.y; height = maxy - miny; lpD3DRM->CreateWrap(D3DRMWRAP_CYLINDER, NULL, D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DDivide(miny, height), D3DVAL(1.0), D3DDivide(-D3DVAL(1.0), height), lpWrap); (*lpWrap)->Apply((LPDIRECT3DRMOBJECT)mesh); } // Creates and applies wrap for texture. void AddMyTexture(LPDIRECT3DRMMESHBUILDER lpMesh, LPDIRECT3DRMTEXTURE * lplpTex) { lpD3DRM->LoadTexture("hello.bmp", lplpTex); lpMesh->SetTexture(*lplpTex); } // Release all D3DRM objects and set the bQuit flag. void CleanUp(void) { gInfo.scene->Release(); gInfo.camera->Release(); gInfo.view->Release(); gInfo.dev->Release(); lpD3DRM->Release(); lpDDClipper->Release(); gInfo.bInit = FALSE; gInfo.bQuit = TRUE; } |
®1998 Adam Perer. All rights reserved. This site was designed by Adam Perer, head of The DirectX Developer Page This site is hosted by Geocities |