#include <iostream> #include <irrlicht.h> using namespace irr; #ifdef _IRR_WINDOWS_ #pragma comment(lib, "irrlicht.lib") //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif enum { //这个IsceneNode ID致命这个场景节点不能被getSceneNodeAndCollisionPointFromRay()拾取 ID_IsNotPickable = 0, //这个标记表面能被拾取 IDFlag_IsPickable = 1 << 0, //这个标记表面节点被拾取后高亮显示, //这个例子中地图不能高亮,而角色能高亮 IDFlag_IsHighlightable = 1 << 1 }; int main(int argc, char** argv) { IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(720, 455), 32, false, true, false, 0); if (!device) return 1; device->setWindowCaption(L"quake3 map"); video::IVideoDriver *driver = device->getVideoDriver(); scene::ISceneManager *smgr = device->getSceneManager(); gui::IGUIEnvironment *guiev = device->getGUIEnvironment(); //为了显示quake3 map,我们要加载它,而其被压缩在map-20kdm2.pk3中, //所以先将压缩包加载到文件系统 //实际调用device->getFileArchive(filename,true,true,EFAT_ZIP); device->getFileSystem()->addZipFileArchive("../media/map-20kdm2.pk3"); //将地图当作一帧动画加载 scene::IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp"); scene::IMeshSceneNode* q3node = 0;//与例子2不一样,eg2是ISceneNode if (q3levelmesh) { q3node = smgr->addOctreeSceneNode(q3levelmesh->getMesh(0), 0, IDFlag_IsPickable); //node = smgr->addMeshSceneNode(mesh->getMesh(0)); } scene::ITriangleSelector* selector = 0; //通过irr::scene::ISceneNode 层的方法对node进行属性调整 //位置:irr::scene::ISceneNodeirr::scene::ISceneNode::setPosition() //旋转:irr::scene::ISceneNode::setRotation() //缩放:irr::scene::ISceneNode::setScale(); if (q3node) { q3node->setPosition(core::vector3df(-1350, -130, -1400)); // node->setRotation(core::vector3df(0, 0, 0)); // node->setScale(core::vector3df(1, 1, 1)); selector = smgr->createOctreeTriangleSelector( q3node->getMesh(), q3node, 128); q3node->setTriangleSelector(selector); } SKeyMap keyMap[5]; keyMap[0].Action = EKA_MOVE_FORWARD; keyMap[0].KeyCode = KEY_KEY_W; keyMap[1].Action = EKA_MOVE_BACKWARD; keyMap[1].KeyCode = KEY_KEY_S; keyMap[2].Action = EKA_STRAFE_LEFT; keyMap[2].KeyCode = KEY_KEY_A; keyMap[3].Action = EKA_STRAFE_RIGHT; keyMap[3].KeyCode = KEY_KEY_D; keyMap[4].Action = EKA_JUMP_UP; keyMap[4].KeyCode = KEY_SPACE; //camera = sceneManager->addCameraSceneNodeFPS(0, 100, 500, -1, keyMap, 8); scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS( 0, 100, .3, ID_IsNotPickable, keyMap, 5, true, 3.0); camera->setTarget(core::vector3df(-70, 30, -60)); if (selector) { scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( selector, camera, core::vector3df(30, 50, 30), core::vector3df(0, -10, 0), core::vector3df(0, 30, 0)); selector->drop(); camera->addAnimator(anim); anim->drop(); } //万事俱备,只需要添加一台摄像机, //maya型的摄像机:irr::scene::ISceneManager::addCameraSceneNodeMaya() //FPS:irr::scene::ISceneManager::addCameraSceneNodeFPS() //smgr->addCameraSceneNodeFPS(); //隐藏鼠标:irr::IrrlichtDevice::ICursorControl device->getCursorControl()->setVisible(false); scene::IBillboardSceneNode* bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); bill->setMaterialTexture(0, driver->getTexture("../media/particle.bmp")); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d<f32>(20, 20)); bill->setID(ID_IsNotPickable); scene::IAnimatedMeshSceneNode* node = 0; node = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../media/faerie.md2"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70, -15, -120)); node->setScale(core::vector3df(2, 2, 2)); node->setMD2Animation(scene::EMAT_POINT); node->setAnimationSpeed(20.0); video::SMaterial material; material.setTexture(0, driver->getTexture("../media/faerie2.bmp")); material.Lighting = true; node->getMaterial(0) = material; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); node = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../media/dwarf.x"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setPosition(core::vector3df(-70, -66, 0)); node->setRotation(core::vector3df(0, -90, 0)); node->setAnimationSpeed(20.0f); selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); node = smgr->addAnimatedMeshSceneNode( smgr->getMesh("../media/ninja.b3d"), 0, IDFlag_IsPickable | IDFlag_IsHighlightable); node->setScale(core::vector3df(10, 10, 10)); node->setPosition(core::vector3df(-70, -66, -60)); node->setRotation(core::vector3df(0, 90, 0)); node->setAnimationSpeed(10); node->getMaterial(0).NormalizeNormals = true; selector = smgr->createTriangleSelector(node); node->setTriangleSelector(selector); selector->drop(); material.setTexture(0, 0); material.Lighting = false; //通用照明灯光 scene::ILightSceneNode* light = smgr->addLightSceneNode(0, core::vector3df(-60, 100, 400), video::SColorf(1.0, 1.0, 1.0, 1.0), 600); light->setID(ID_IsNotPickable); scene::ISceneNode* highlightSceneNode = 0; scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager(); material.Wireframe = true; int lastFPS = -1; while (device->run()) { if (device->isWindowActive()) { driver->beginScene(true, true, video::SColor(255, 100, 101, 140)); smgr->drawAll(); guiev->drawAll(); //将高亮节点重置 if (highlightSceneNode) { highlightSceneNode->setMaterialFlag(video::EMF_LIGHTING, true); highlightSceneNode = 0; } //设置射线:摄像机到视线外1000距离处 //可以创建一个从鼠标点击处产生的射线: //ISceneCollisionManager::getRayFromScreenCoordinates() core::line3d<f32> ray; ray.start = camera->getPosition(); ray.end = ray.start + (camera->getTarget() - ray.start).normalize()*1000.0f; core::vector3df intersection;//跟踪当前交点 core::triangle3df hitTriangle;//显示拾取到的三角形用 //通过这个函数获得被拾取的节点, //同时获取焦交点,被拾取的三角形 scene::ISceneNode* selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray,// intersection, hitTriangle, IDFlag_IsPickable,//id, 0);//从这个节点开始遍历, if (selectedSceneNode) { bill->setPosition(intersection); //在绘制执行自己的绘制程序前,重置变换矩阵 driver->setTransform(video::ETS_WORLD, core::matrix4()); driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0, 255, 0, 0));//绘制出被击中的三角形 //处理能被高亮的节点 if ((selectedSceneNode->getID()&IDFlag_IsHighlightable) == IDFlag_IsHighlightable) { highlightSceneNode = selectedSceneNode; highlightSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);//事实上就是关闭其光照属性, } } driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"quake3 map ["; str += driver->getName(); str += "]FPS.", str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } else //闲置,一直渲染占用过多cpu资源 device->yield(); } device->drop(); return 0; }