#include
#include
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(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(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 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;
}