这个例子仅可在Windows环境下运行,它可以证明Irr可以在一个Win32窗口内运行。


// 这个例子仅可在Windows环境下运行,它可以证明Irr可以在一个Win32窗口内运行。

#include <irrlicht.h>
#ifndef _IRR_WINDOWS_
#error Windows only example
#else
#include <windows.h> // 这个例子仅可运行于Windows环境下

using namespace irr;

#pragma comment(lib, "irrlicht.lib")

HWND hOKButton;
HWND hWnd;

static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
   {
    HWND hwndCtl = (HWND)lParam;
    int code = HIWORD(wParam);

    if (hwndCtl == hOKButton)
    {
     DestroyWindow(hWnd);
     PostQuitMessage(0);
     return 0;
    }
   }
   break;
case WM_DESTROY:
   PostQuitMessage(0);
   return 0;

}

return DefWindowProc(hWnd, message, wParam, lParam);
}



int main()
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hpre, LPSTR cmd, int cc)
{
HINSTANCE hInstance = 0;

const char* Win32ClassName = "CIrrlichtWindowsTestDialog";

WNDCLASSEX wcex;
wcex.cbSize    = sizeof(WNDCLASSEX);
wcex.style    = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)CustomWndProc;
wcex.cbClsExtra   = 0;
wcex.cbWndExtra   = DLGWINDOWEXTRA;
wcex.hInstance   = hInstance;
wcex.hIcon    = NULL;
wcex.hCursor   = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName = 0;
wcex.lpszClassName = Win32ClassName;
wcex.hIconSm   = 0;

RegisterClassEx(&wcex);

DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
   WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;

int windowWidth = 440;
int windowHeight = 380;

hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example",
   style, 100, 100, windowWidth, windowHeight,
   NULL, NULL, hInstance, NULL);

RECT clientRect;
GetClientRect(hWnd, &clientRect);
windowWidth = clientRect.right;
windowHeight = clientRect.bottom;

// 创建OK按钮
hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT,
   windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);

// 创建一些静态文字

CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\
   "Also mixing with MFC and .NET Windows.Forms is possible.",
   WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);

// 创建一个BUTTON子窗口以提供Irr使用

HWND hIrrlichtWindow = CreateWindow("BUTTON", "", WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
    50, 80, 320, 220, hWnd, NULL, hInstance, NULL);

// 在BUTTON子窗口中创建一个Irr设备
irr::SIrrlichtCreationParameters param;
param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow);
param.DriverType = video::EDT_OPENGL;

irr::IrrlichtDevice* device = irr::createDeviceEx(param);

// 设置一个简单的3D场景

irr::scene::ISceneManager* smgr = device->getSceneManager();
video::IVideoDriver* driver = device->getVideoDriver();

scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0));

scene::ISceneNodeAnimator* anim = smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam->addAnimator(anim);
anim->drop();

scene::ISceneNode* cube = smgr->addCubeSceneNode(20);

cube->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
cube->setMaterialTexture(1, driver->getTexture("../../media/water.jpg"));
cube->setMaterialFlag( video::EMF_LIGHTING, false );
cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );

smgr->addSkyBoxSceneNode(
driver->getTexture("../../media/irrlicht2_up.jpg"),
driver->getTexture("../../media/irrlicht2_dn.jpg"),
driver->getTexture("../../media/irrlicht2_lf.jpg"),
driver->getTexture("../../media/irrlicht2_rt.jpg"),
driver->getTexture("../../media/irrlicht2_ft.jpg"),
driver->getTexture("../../media/irrlicht2_bk.jpg"));

// 显示Windows窗口
ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd);

/*
你可以简单的使用GetMessage,DispatchMessage等消息循环。然后在其中调用Device->Run()
的话Irr引擎就可以获取Windows的消息分发了。
但是如果你不调用Device->run()的话,你就无法获取Windows分发的用户输入信息。那么你只能
自己使用DirectInput等东西来获取。
*/

while (device->run())
{
   driver->beginScene(true, true, 0);
   smgr->drawAll();
   driver->endScene();
}

// 如果你没有调用Device->run()你就必须这样自己获取消息了,代码如下

/*
MSG msg;
while (true)
{
   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
   {
    TranslateMessage(&msg);
    DispatchMessage(&msg);

    if (msg.message == WM_QUIT)
     break;
   }

   // advance virtual time
   // (译者注:此处此函数调用目的不明,故保持原状不做翻译,望高手来函指点)
   device->getTimer()->tick();

   // 绘制渲染引擎场景
   driver->beginScene(true, true, 0);
   smgr->drawAll();
   driver->endScene();
}*/

device->closeDevice();
device->drop();

return 0;
}
#endif // if windows