# Why is my screen centered 0,0 in the middle of screen?

This topic is 1675 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am using Irrlicht 1.8 and when I try and setup a orthogonal projection with buildProjectionMatrixOrthoRH(), if I position the object it's (0,0) origin is the middle of the screen... I would like to have the coordinates start with the top or bottom left as the 0,0 point.

If I call draw2DPolygon() the top left is (0,0) and if I call drawIndexedTriangleFan() or draw2DVertexPrimitiveList() the center of the screen is (0,0)

I am not sure why this is, but need to get this solved.

http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=48773

##### Share on other sites
I don’t know the Irrlicht API but there is no way to accomplish what you want with that method; it automatically centers the projection.
Most API’s would give you an “offset” version of the same method, but apparently Irrlicht does not.

So you have to make one yourself.
Here is the code that would be plug-and-play for their matrix library:
     // Builds a customized, right-handed orthographic projection matrix.
template <class T>
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoOffCenterRH(
f32 left, f32 right, f32 bottom, f32 top, f32 zNear, f32 zFar)
{
T width = (T)(right-left);
T height = (T)(top-bottom);
_IRR_DEBUG_BREAK_IF(width==0.f); //divide by zero
_IRR_DEBUG_BREAK_IF(height==0.f); //divide by zero
_IRR_DEBUG_BREAK_IF(zNear==zFar); //divide by zero

M[0] = (T)(2/width);
M[1] = 0;
M[2] = 0;
M[3] = 0;

M[4] = 0;
M[5] = (T)(2/height);
M[6] = 0;
M[7] = 0;

M[8] = 0;
M[9] = 0;
M[10] = (T)(1/(zNear-zFar));
M[11] = 0;

M[12] = (T)((left+right)/(left-right));
M[13] = (T)((top+bottom)/(bottom-top));
M[14] = (T)(zNear/(zNear-zFar));
M[15] = 1;

#if defined ( USE_MATRIX_TEST )
definitelyIdentityMatrix=false;
#endif
return *this;
}
Their original code can be found here:
http://irrlicht.sourceforge.net/docu/matrix4_8h_source.html
buildProjectionMatrixOrthoRH() is defined on line 01639, and I based my version off that. Both are right-handed and row-major.

L. Spiro Edited by L. Spiro

##### Share on other sites
L. Spiro

THANK you! That did the trick!!! Odd that the developers at Irrlicht don't have the ability to choose this seems simple to add the parameter on calling the buildProjectionMatrixOrthoRH() to make it offset... :)

##### Share on other sites

Another option is to add a translation (by width / 2 and height / 2) to your transforms.

##### Share on other sites

One last quick question, how can I change the buildProjectionMatrixOrthoOffCenterRH() to be LH()?

Thanks!

##### Share on other sites

M[10] = (T)(1/(zFar-zNear));

##### Share on other sites

Or call buildProjectionMatrixOrthoLH instead.

##### Share on other sites

Or call buildProjectionMatrixOrthoLH instead.

Which works if combined with your previous post (manually doing translations).

If you want the matrix to handle the translations for you, then you need L. Spiro's implementation.

##### Share on other sites

One last question, I am trying to use

irr::scene::IParticleEmitter

with this custom Projection matrix and it will not render the position correctly? Do I need to make my own particle class to use this?

It renders the effect at 0,0,0 when I set position to that, but if I use 400, 0, their isn't anything on screen. Screen size is 800,600 so it should be at middle bottom of screen...


void NX::Effect::DrawEffect(irr::IrrlichtDevice* device,
irr::video::IVideoDriver* driver)
{
NX::App* p = NX::App::Get();

irr::core::matrix4 oldProjMat  = driver->getTransform(irr::video::ETS_PROJECTION);
irr::core::matrix4 oldViewMat  = driver->getTransform(irr::video::ETS_VIEW);
irr::core::matrix4 oldWorldMat = driver->getTransform(irr::video::ETS_WORLD);

irr::core::matrix4 projMatrix;
NX::BuildProjMatrixOrthoOffCenterRH(0.0f, p->GetAppConfig()->screenSize.Width,
0.0f, p->GetAppConfig()->screenSize.Height,
-1.0f, 100.0f,
projMatrix);

driver->setTransform(irr::video::ETS_PROJECTION, projMatrix);
driver->setTransform(irr::video::ETS_VIEW,  irr::core::matrix4());
driver->setTransform(irr::video::ETS_WORLD, irr::core::matrix4());

if(!ps)
//irr::scene::IParticleSystemSceneNode* ps = device->getSceneManager()->addParticleSystemSceneNode(false);
//irr::scene::IParticleEmitter* em         = ps->createRingEmitter(pos, .005f, .05f);

//em->setMinStartSize(irr::core::dimension2d<irr::f32>(.1f, .1f));
//em->setMaxStartSize(irr::core::dimension2d<irr::f32>(.5f, .5f));

//irr::scene::IParticleEmitter* em = ps->createRingEmitter(pos, 0.0f, 5.0f, irr::core::vector3df(0.0f, 0.0f, .01f));
if(!em)
{
em = ps->createRingEmitter(pos, 0.0f, 1.0f, irr::core::vector3df(0.0f, 0.0f, 0.0f));
em->setMinStartSize(irr::core::dimension2d<irr::f32>(1.0f, 1.0f));
em->setMaxStartSize(irr::core::dimension2d<irr::f32>(1.0f, 1.0f));
ps->setEmitter(em);
em->drop();
}

//irr::scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
if(!paf)
{
paf->drop();
ps->setMaterialFlag(irr::video::EMF_LIGHTING, false);
ps->setMaterialFlag(irr::video::EMF_ZWRITE_ENABLE, false);
ps->setMaterialTexture(0, driver->getTexture("media/portal6.png"));
}
else
{
ps->setMaterialFlag(irr::video::EMF_LIGHTING, false);
ps->setMaterialFlag(irr::video::EMF_ZWRITE_ENABLE, false);
driver->enableMaterial2D(true);
}
}


Thanks!

Edited by MARS_999

##### Share on other sites

I would expect [0, 0] to be the upper-left, not the lower-left.

In any case, using the new projection matrix, [400, 300] is exactly the same as [0, 0] in the previous projection matrix (center of the screen).

I would suggest using that as your test case as it may very well be that your particles are all shooting upwards and since your Y is 0, all particles start at the top of the screen and fly even further off the top of the screen, meaning you can never see them.

L. Spiro

##### Share on other sites

I would expect [0, 0] to be the upper-left, not the lower-left.

In any case, using the new projection matrix, [400, 300] is exactly the same as [0, 0] in the previous projection matrix (center of the screen).

I would suggest using that as your test case as it may very well be that your particles are all shooting upwards and since your Y is 0, all particles start at the top of the screen and fly even further off the top of the screen, meaning you can never see them.

L. Spiro

I don't think so, I changed to Z axis and tried 0,0,0 for the position and it's still at center of screen... If I use 10,0,0 it move way over to the right side barely visible...

So for some reason the uploaded projection matrix isn't working?

##### Share on other sites

I see a bunch of preparation code but no draw call.  By the time the draw call is issued you probably have a perspective matrix applied.  If the particles get small as you increase/decrease their Z then you have a perspective projection.

L. Spiro

##### Share on other sites

I see a bunch of preparation code but no draw call.  By the time the draw call is issued you probably have a perspective matrix applied.  If the particles get small as you increase/decrease their Z then you have a perspective projection.

L. Spiro

i am using this example.

http://irrlicht.sourceforge.net/docu/example008.html

they have no draw*() calls...

thanks

##### Share on other sites
That example creates a camera. If you are creating a camera in your code as well (following the example) then the camera will probably overwrite your direct driver::setTransform() calls during scene rendering. Why are you trying to bypass the built-in camera system and setting driver transform state directly? Just create an ICameraSceneNode as in the example, and manipulate that to get your desired perspective and view transforms. ICameraSceneNode even includes a method for setting the projection matrix directly.

##### Share on other sites

I am not using any camera at all in my code. I am just keeping the camera at 0,0,0 and rendering a screen and just want to work with the screen coordinates in x,y ortho view. This is a simple 2d game that never moves the camera...

Hello Josh!!!

##### Share on other sites

Yes, but the scene manager applies the camera's projection before rendering the scene, so any projection mucking you've done prior the the scene being rendered gets undone. You need to set the camera's projection matrix to ortho instead of mucking about with the device directly as JTippetts pointed out.

##### Share on other sites

I am using this code.

    irr::core::matrix4 projMatrix;
projMatrix = projMatrix.buildProjectionMatrixOrthoRH(config.screenSize.Width, config.screenSize.Height, 1.0f, 100.0f);
camera->setProjectionMatrix(projMatrix, true);


and no luck...

Thanks!

##### Share on other sites

The main point is that we don’t know what happens inside the camera class in Irrlicht, so we don’t know what to make of the evidence, frankly.

There could be a number of things that would cause that matrix to be overwritten by the camera class itself.

Evidence suggests that a perspective projection is what gets fed to the graphics card at the end of the day, so you need to be searching by yourself for how that could possibly happen.  While you continue trying things to correct this problem, if they don’t work you need to think about “what else” could cause the problem to persist.  In this case, my first reaction would be to say that something is overwriting the camera matrix afterwards.  After all, you are changing things on your end, but the visual result is the same, so it must follow that your changes have either no meaning to the end result or are overwritten.

All you can do from there is keep reading about Irrlicht and keep trying your own experiments.

The secondary point is that “projMatrix = ” is superfluous.  Since I have seen the source code I know that that method modifies itself, and then returns itself.  Then you make a copy of itself into itself.  It’s not necessary to receive the return value from projMatrix.buildProjectionMatrixOrthoRH(); by the time it returns, projMatrix has already been filled with the correct values.

L. Spiro

##### Share on other sites

http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=48813

I have made some progress, but please look at the link above and read the last two posts.... It seems like I have to use half width to get the object on screen now... and Y is upside down DX upper left 0,0 vs. GL bottom left 0,0

##### Share on other sites

I think you need some clarification. If your view and projection matricies are identities (not set), you get an orthogonal observation and your screen will contain only objects that are in -1 , 1 scope. That is, that if you have object of 4 verticies with values in object space (the object space equals your projection space now) such as 1.0,0.0, it will be placed at vertical center and at right edge of screen, and 0.0,0.0 will be placed at the center, -1.0,1.0 is the upper left corner. Do not confuse this with placing at screen resolution coordinates, 100,100 will place the thing 100 screens to the right up! If you want to place by screen pixel width height, divide by dimensions of screen then. Also realize that ortho camera has its certain scope of view, so if you devide everything by some value, say 1000, then you will be observing 1000.0,-1000.0 square, thus then -1000.0,1000.0 is your upper left corner. You cans still apply some world matricies to the objects. Also finaly, ortho camera may have rotation but this is often not desired, but ortho camera may need translation. So you should set up a view matrix with translation only, and apply that matrix. So in the end you are using only world matrcies per object, view matrix with only translation, and a projection matrix that only scales thing down by a single division. Possibly

##### Share on other sites

I think you need some clarification. If your view and projection matricies are identities (not set), you get an orthogonal observation and your screen will contain only objects that are in -1 , 1 scope. That is, that if you have object of 4 verticies with values in object space (the object space equals your projection space now) such as 1.0,0.0, it will be placed at vertical center and at right edge of screen, and 0.0,0.0 will be placed at the center, -1.0,1.0 is the upper left corner. Do not confuse this with placing at screen resolution coordinates, 100,100 will place the thing 100 screens to the right up! If you want to place by screen pixel width height, divide by dimensions of screen then. Also realize that ortho camera has its certain scope of view, so if you devide everything by some value, say 1000, then you will be observing 1000.0,-1000.0 square, thus then -1000.0,1000.0 is your upper left corner. You cans still apply some world matricies to the objects. Also finaly, ortho camera may have rotation but this is often not desired, but ortho camera may need translation. So you should set up a view matrix with translation only, and apply that matrix. So in the end you are using only world matrcies per object, view matrix with only translation, and a projection matrix that only scales thing down by a single division. Possibly

Thanks johnny for the explanation, so do you have some code of this in action? I never had to setup this before. So I could learn from that code? I am using Irrlicht obviously...

THanks!

##### Share on other sites

SHOOT me!!!!

I found it... sigh...

IParticleSystemSceneNode* ps;

ps->setPosition();

I called that when I was rendering which sets the relative to its parent node...

I took that out and now we are running smooth! :)

Thanks for the help and explanation!!!