using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;
/*==============================================================================
Receiver class
==============================================================================*/
class MyEventReceiver : public IEventReceiver
{
bool KeyIsDown[KEY_KEY_CODES_COUNT];
bool LEFTBUTTONCLICKED;
bool RIGHTBUTTONCLICKED;
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
if(event.EventType == EET_MOUSE_INPUT_EVENT)
{
if (event.MouseInput.Event==EMIE_LMOUSE_PRESSED_DOWN) LEFTBUTTONCLICKED = true;
else if(event.MouseInput.Event==EMIE_LMOUSE_LEFT_UP ) LEFTBUTTONCLICKED = false;
else if(event.MouseInput.Event==EMIE_RMOUSE_PRESSED_DOWN) RIGHTBUTTONCLICKED = true;
else if(event.MouseInput.Event==EMIE_RMOUSE_LEFT_UP ) RIGHTBUTTONCLICKED = false;
}
return false;
}
virtual bool IsKeyDown(EKEY_CODE keyCode) const { return KeyIsDown[keyCode]; }
virtual bool IsLMBDown() const { return LEFTBUTTONCLICKED; }
virtual bool IsRMBDown() const { return RIGHTBUTTONCLICKED; }
MyEventReceiver()
{
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = false;
LEFTBUTTONCLICKED = RIGHTBUTTONCLICKED = false;
}
};
/*==============================================================================
Raise or lower terrain (selected vertice)
==============================================================================*/
void RaiseTerrainVertex(ITerrainSceneNode* terrain, s32 index, f32 step, bool up)
{
IMesh* pMesh = terrain->getMesh();
s32 b;
for (b=0; b<pMesh->getMeshBufferCount(); ++b)
{
IMeshBuffer* pMeshBuffer = pMesh->getMeshBuffer(b);
// skip mesh buffers that are not the right type
if (pMeshBuffer->getVertexType() != video::EVT_2TCOORDS) continue;
video::S3DVertex2TCoords* pVertices = (video::S3DVertex2TCoords*)pMeshBuffer->getVertices();
pVertices[index].Pos.Y += (up) ? step : -step;
}
// force terrain render buffer to reload
terrain->setPosition(terrain->getPosition());
}
/*==============================================================================
Save file
==============================================================================*/
void save (IVideoDriver* driver, ITerrainSceneNode* terrain)
{
core::dimension2d<s32> dim (256,256);
video::IImage *img = driver->createImage(ECF_R8G8B8, dim);
u32 VertexCount = terrain->getMesh()->getMeshBuffer(0)->getVertexCount();
S3DVertex2TCoords* verts = (S3DVertex2TCoords*)terrain->getMesh()->getMeshBuffer(0)->getVertices();
for (u32 i=0; i<VertexCount; i++)
{
S3DVertex2TCoords* vertex = verts + i;
u8 y = (u8)vertex->Pos.Y;
img->setPixel((u32)vertex->Pos.X, (u32)vertex->Pos.Z, video::SColor(0, y,y,y));
}
driver->writeImageToFile(img, "heightmap.bmp", 0);
img->drop();
}
/*==============================================================================
Entry point
==============================================================================*/
int main()
{
IrrlichtDevice* device = createDevice(EDT_OPENGL, dimension2d<s32>(800,600), 32, false);
if (!device) return 0;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
device->getCursorControl()->setVisible(false);
device->setWindowCaption(L"terrain");
MyEventReceiver receiver;
device->setEventReceiver(&receiver);
// Terrain
ITerrainSceneNode* terrain = smgr->addTerrainSceneNode("heightmap.bmp");
terrain->setScale(core::vector3df(32, 2.f, 32));
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0, driver->getTexture("aer.jpg"));
ITriangleSelector* terrainSelector = smgr->createTerrainTriangleSelector(terrain, 0);
// Camera
scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, .1f);
cam->setPosition(core::vector3df(-100,500,100));
cam->setTarget(core::vector3df(0,0,0));
// Arrow
ISceneNode* arrow = smgr->addAnimatedMeshSceneNode(smgr->addArrowMesh("arrow",
SColor(255, 255, 0, 0), SColor(255, 0, 255, 0)), NULL);
arrow->setMaterialFlag(video::EMF_LIGHTING, false);
arrow->setScale(vector3df(20,20,20));
arrow->setRotation(vector3df(0,0,180));
// GUI
IGUIEnvironment* guienv = device->getGUIEnvironment();
IGUIFont* font = guienv->getFont("battlefield.bmp");
guienv->getSkin()->setFont(font);
IGUIStaticText* txt[2];
txt[0] = guienv->addStaticText(L"Left/Right Mouse Button : raise/lower\nF4/F5 : increase/decrease step\nW : switch wireframe\nS : save heightmap",
core::rect<s32>(10,10,600,120), false, true, 0, -1, false);
txt[0]->setOverrideColor(video::SColor(255,150,100,60));
txt[1] = guienv->addStaticText(L"", core::rect<s32>(10,80,600,200), false, true, 0, -1, false);
txt[1]->setOverrideColor(video::SColor(255,0,255,0));
ITimer* irrTimer = device->getTimer();
u32 then = 0, then30 = 0;
char c[24];
f32 step = 2.f;
bool wireframe = false;
while(device->run()) if (device->isWindowActive())
{
u32 now = irrTimer->getTime();
if (then30 < now)
{
if(receiver.IsKeyDown(irr::KEY_ESCAPE)) break;
if (receiver.IsKeyDown(irr::KEY_KEY_W) && then < now)
{
wireframe = !wireframe;
terrain->setMaterialFlag(video::EMF_WIREFRAME, wireframe);
then = now + 300;
}
if (receiver.IsKeyDown(irr::KEY_F4) && then < now)
{
step += 1.f;
then = now + 100;
}
else if (receiver.IsKeyDown(irr::KEY_F5) && then < now && step > 0)
{
step -= 1.f;
then = now + 100;
}
if(receiver.IsKeyDown(irr::KEY_KEY_S))
save (driver, terrain);
// move the arrow to the nearest vertex ...
const position2di clickPosition = device->getCursorControl()->getPosition();
const line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(clickPosition, cam);
vector3df pos;
triangle3df Tri;
if (smgr->getSceneCollisionManager()->getCollisionPoint(ray, terrainSelector, pos, Tri))
{
//arrow->setPosition(pos);
static const s32 scale = 32; // terrain is scaled 32X
static const s32 size = 256; // heightmap is 256X256 pixels
s32 x = (s32)(pos.X / scale);
s32 z = (s32)(pos.Z / scale);
s32 index = x * size + z;
// ... Move it if clicked
if( (receiver.IsLMBDown() || receiver.IsRMBDown()) && then < now)
{
RaiseTerrainVertex(terrain, index, step, receiver.IsLMBDown());
then = now + 100;
}
x *= scale;
z *= scale;
arrow->setPosition(vector3df(x, terrain->getHeight(x, z) + 20, z));
}
driver->beginScene(true, true, video::SColor(255,0,0,0));
smgr->drawAll();
sprintf(c,"elevation step : %.0f units", step);
txt[1]->setText(stringw(c).c_str());
guienv->drawAll();
driver->endScene();
then30 = now + 30;
} // 30Hz
}
device->closeDevice();
device->drop();
return 0;
}
'etc > irrlicht' 카테고리의 다른 글
xcode 로 일리히트엔진 사용기 1 (3) | 2010.06.25 |
---|---|
일리히트엔진 강좌(irrlicht 강좌) (1) | 2010.06.06 |
일리히트 터래인툴관련 소스입니다. (0) | 2010.05.01 |
동적 반사 데모입니다.(소스포함) (0) | 2010.01.03 |
굴절데모입니다.(소스포함) (0) | 2010.01.03 |