If you use an orthographic camera, your object sizes will be consistent fractions of whatever view size you specify. As you're doing a 2d visualisation, an orthographic projection is probably more suitable anyway.
This example uses 2 viewports just to show two different 'screen' resolutions at the same time. You generally don't have to mess around with viewports: the important part is setting an orthogonal camera projection matrix, and sizing and positioning your objects using an appropriate fraction of the widthOfViewVolume and heightOfViewVolume that you set in the orthogonal matrix.
Code: Select all
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
#define IRRLICHT_SVN_OR_1_5 0
int main()
{
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<s32>(800, 800));
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
// Use 2 viewports, one 800 x 600 (4:3), one 355 x 200 (16:9)
rect<s32> viewPort1(0, 0, 800, 600);
rect<s32> viewPort2(0, 600, 355, 800);
// Build an orthogonal matrix that says the screen is 100 x 100. This means that an object
// that is 100 x 100 will exactly fill the screen (or in this case, viewport) regardless
// of how big (in pixels) the screen or viewport actually is.
matrix4 orthogonalMatrix;
orthogonalMatrix.buildProjectionMatrixOrthoLH(100.f, 100.f, 1.f, 50.f);
// Add a cameras
ICameraSceneNode * camera = smgr->addCameraSceneNode();
camera->setPosition(vector3df(0, 0, -20));
// Now make the camera orthographic. The method to do that has changed since 1.4.2
#if IRRLICHT_SVN_OR_1_5
camera->setProjectionMatrix(orthogonalMatrix, true); // SVN / Irrlicht 1.5
#else
camera->setProjectionMatrix(orthogonalMatrix); // <= 1.4.2
camera->setIsOrthogonal(true);
#endif
// Create one billboard that is 25% and 50% of the height and width of the orthogonal view
// size, and offset 25% to the left and above screen centre.
scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
bill->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setPosition(vector3df(-25.f, 25.f, 0.f));
bill->setSize(core::dimension2d<f32>(25.f, 50.f));
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
// Reset the viewport to the whole screen
driver->setViewPort(rect<s32>(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height));
// And draw a background in each viewport so that we can see their bounds.
driver->draw2DRectangle(SColor(255, 255, 0, 0), viewPort1);
driver->draw2DRectangle(SColor(255, 0, 255, 0), viewPort2);
// Now render to the first viewport.
driver->setViewPort(viewPort1);
smgr->drawAll();
// And render the same scene to the second viewport, with a different pixel resolution.
driver->setViewPort(viewPort2);
smgr->drawAll();
// Note that in both viewports, the billboard takes up the same proportion of the 'screen'
// and is at the same relative position.
driver->endScene();
}
device->drop();
return 0;
}