[fixed]Strange circle with billboard and ortho camera

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

[fixed]Strange circle with billboard and ortho camera

Post by MartinVee »

I set up an orthographic view with a nearZ of 0.0f and a farZ of 1000.0f. I then created a few billboards (with a simple bee texture) that I put at a Z distance of 20.0f, and then I created four billboards without texture (i.e. colored rectangles, each with their own color) with a Z distance of 1.0f. Since the four billboards have a value of 70 as the alpha component of their colors, I expected to see my textured billboards through them, but when I tested, that's not what happened. Some of the textured billboards looked like they were on top of the colored billboards, and some others looked like they were behind (like I expected).

That seemed odd enough, and I tested further. I checked the Z component of the billboards positions, I played with the distances, I added textured billboards, and I finally came up with this :

Image

That's 15,000 textured billboards with four colored billboards. Like I said, the textured billboard have a higher Z value than the colored ones, so I expected them to be drawn behind the rectangles. That's not the case for a circle-shaped area right in the center. If I play with the Z values by pulling the billboards apart on the Z axis, the circle shrinks. If I pull them apart enough (let's say around 1.0f for the colored billboards, and 800.0f for the textured billboards), then the circle disappears and everything works as intended (opinion : in fact, I do believe that the circle is then too small to be noticable, but I don't have a firm grasp of the mecanisms at work to be confident in that assumption).

This seems very strange to me. It's probably a problem somewhere in my code, but... Why is it doing that? Is it a side effect of using an orthographic view? What should I check next to understand the problem and correct it?
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

Sorry, really hard to understand a description of what code is doing in english. Maybe post the code. And explain once more what exactly you expect to see.

One note... you said you expect that higher Z value means being drawn behind. But you might confuse z-axis value with z-buffer value. If a higher z-axis value is front or behind something depends on the position and direction of your camera. If it's below your objects it's as you thought, if it's above your objects it's the other way round.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Can someone please validate my theory, and fill in the gaps in my knowledge?

I looked through the code of drawAll() and I've seen the following steps happening :
  1. render the cameras
  2. render the light nodes
  3. render the skyboxes
  4. render the solid nodes
  5. render the shadow nodes
  6. render the transparent nodes (emphasis mine)
  7. render the transparent effect nodes
On step #6, when the transparent nodes are rendered, the TransparentNodeList is sorted by distance from the camera (which is fine, as far as I can tell, because everything needs to be drawn from the farthest to the closest). The node distance from its camera is calculated using this method :

Code: Select all

 
Distance = Node->getAbsoluteTransformation().getTranslation().getDistanceFromSQ(camera);
 
When I checked the values of Distance, I saw that the values for my four colored billboards were :
  • 101811.0
  • 97971.0
  • 106931.0
  • 103091.0
... and all the textured billboards that are located in that circle have lower values for distance (as low as 40000.0 for the ones close to the center). This means that the sorting algorithm makes those billbords be drawn after the colored billboards, which, in my previous understanding, wasn't possible since the distance was calculated using the Z component of the position.

Does my thoery holds up?

Now, as to how I could possibly correct this problem, I really don't know. I realized I don't know a whole lot about orthographic views and how they're working. For example, I don't understand why the distance from the camera can be several order of magnitude greater than my view distance (1000.0f). Those maybe wrong assumptions.

What would be the best course of action? Does it mean my camera isn't setup correctly? Would I need to reimplement a SceneManager? Any ideas?

Thanks a lot!
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

CuteAlien : thanks for your reply. You're right, I was thinking about creating a basic test case for it. I'll get to it and get back to you!
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Here's a sample code that reproduces the behaviour I'm seeing :

Code: Select all

 
#include <windows.h>
#include <irrlicht.h>
 
#include "main.h"
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
#ifdef _IRR_WINDOWS_
  #pragma comment(lib, "Irrlicht.lib")
  #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
 
#define NB_STRESS_TEST (10000)
 
#define SCREEN_WIDTH (1024)
#define SCREEN_HEIGHT (768)
 
 
int main(int argc, const char* argv[])
{
  IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D9, dimension2d<u32>(SCREEN_WIDTH, SCREEN_HEIGHT), 32, false, false, false, NULL);
 
  if(device)
  {
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
 
    // Declare a screensize object using the values from the driver
    const core::dimension2d<u32> screenSize = driver->getScreenSize();
 
    // Add a camera node
    ICameraSceneNode *cam = device->getSceneManager()->addCameraSceneNode(0, irr::core::vector3df((f32)screenSize.Width / 2, -((f32)(screenSize.Height / 2)), -1), irr::core::vector3df((f32)screenSize.Width / 2, -((f32)(screenSize.Height / 2)), 100));
 
    // Create a projection matrix to translate a 3D view to the exact screen size, and an orthographic field of view of 1000 units.
    matrix4 projectionMatrix;
    projectionMatrix.buildProjectionMatrixOrthoLH((f32)screenSize.Width, (f32)screenSize.Height, 0.0f, 1000.0f);
 
    // Apply the projection matrix to the camera.
    cam->setProjectionMatrix(projectionMatrix, true);
 
    // The world and the view needs to be reset to the identity matrix, in order to remove any matrix transformation for field of view.
    driver->setTransform(video::ETS_WORLD, core::matrix4());
    driver->setTransform(video::ETS_VIEW, core::matrix4());
 
    // Note that performance is not the issue here.
    ISceneNode* testNodes[NB_STRESS_TEST];
    for(int iNode = 0; iNode < NB_STRESS_TEST; iNode++)
    {
      testNodes[iNode] = smgr->addBillboardSceneNode(NULL, core::dimension2df((f32)8, (f32)8));
      testNodes[iNode]->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
      testNodes[iNode]->setMaterialFlag(video::EMF_LIGHTING, false);
    }
 
    // Gap of 25 pixels on the sides as a validation that the billboards are really white.
    dimension2du gap = dimension2du(25, 25);
    // Size of a colored billboard
    dimension2du cbSize = dimension2du(screenSize.Width/2 - gap.Width, screenSize.Height/2 - gap.Height);
 
    // The four semi-transparent billboards.
    ISceneNode* transparentBillboards[4];
    // Colors of the billboards
    SColor tbColors[4] =
    {
      SColor(150, 255, 0, 0),
      SColor(150, 255, 255, 0),
      SColor(150, 0, 255, 255),
      SColor(150, 0, 0, 255),
    };
 
    transparentBillboards[0] = smgr->addBillboardSceneNode(NULL, core::dimension2df((f32)cbSize.Width, (f32)cbSize.Height), core::vector3df(gap.Width + (cbSize.Width / 2), -(f32)gap.Height - (cbSize.Height / 2), 1.0f), -1, tbColors[0], tbColors[0]);
    transparentBillboards[1] = smgr->addBillboardSceneNode(NULL, core::dimension2df((f32)cbSize.Width, (f32)cbSize.Height), core::vector3df(screenSize.Width - gap.Width - (cbSize.Width / 2), -(f32)gap.Height - (cbSize.Height / 2), 1.0f), -1, tbColors[1], tbColors[1]);
    transparentBillboards[2] = smgr->addBillboardSceneNode(NULL, core::dimension2df((f32)cbSize.Width, (f32)cbSize.Height), core::vector3df(gap.Width + (cbSize.Width / 2), -(f32)screenSize.Height + gap.Height + (cbSize.Height / 2), 1.0f), -1, tbColors[2], tbColors[2]);
    transparentBillboards[3] = smgr->addBillboardSceneNode(NULL, core::dimension2df((f32)cbSize.Width, (f32)cbSize.Height), core::vector3df(screenSize.Width - gap.Width - (cbSize.Width / 2), -(f32)screenSize.Height + gap.Height + (cbSize.Height / 2), 1.0f), -1, tbColors[3], tbColors[3]);
 
    for(int iNode = 0; iNode < 4; iNode++)
    {
      transparentBillboards[iNode]->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
      transparentBillboards [iNode]->setMaterialFlag(video::EMF_LIGHTING, false);
    }
 
    u32 currentTime = device->getTimer()->getTime();
    while(device->run())
    {
      // Poor man's way of randomizing the white billboards position at each 200 ms
      if(device->getTimer()->getTime() > currentTime + 200)
      {
        for(int i = 0; i < NB_STRESS_TEST; i++)
        {
          f32 X = (rand() % (screenSize.Width - 4));
          f32 Y = 0.0f - (rand() % (screenSize.Height - 4));
          f32 Z = 50.0f;
          testNodes[i]->setPosition(core::vector3df(X, Y, Z));
        }
        currentTime = device->getTimer()->getTime();
      }
 
      // The rendering
      driver->beginScene(true, true, SColor(255, 0, 0, 0));
      smgr->drawAll();
      driver->endScene();
    }
  }
 
  device->drop();
 
  return 0;
}
 
Please note that this code is not the prettiest I ever wrote, nor the fastest. It was written purely as a demonstration of my perceived problem.

All white billboards have their Z-position set to 50.0f and the four semi-transparent billboards have a Z-position of 1.0f. There's 10,000 white billboards because it's easier to see the problem (i.e. the round area where the billboards are rendered on top), but the problem's still present with fewer billboards.

Here's the result I'm getting :

Image

What I'm expecting to see is the four semi-transparents billboards in front of all the small white billboards. Here's a top-down view of my comprehension on how I set up the camera/world :

Image

Please disregard my "mad skills" with MSPaint. :wink:

I'm sure there's something I'm not understanding correctly. From what CuteAlien said, I think it might be the camera's position? Don't hesitate to set me straight, as I'm sure I made a wrong assumptions somewhere, and I'm really looking to learn the ropes of 3D development (since I come from 2D gaming development).
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Hi again,

I don't like bumping threads, but I really need an answer to my problem, as I frankly don't understand what I did wrong.

Maybe just a few pointers, or potential problematic things to check?

Like I said earlier, my guess is that my nodes gets sorted in a way I wasn't expecting, but I'm still not sure if I really understand what's going on.

Thanks a lot!
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

You'll have to wait at least until weekend... too much code to check that on the side.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Excellent! Thanks for the feedback!
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

Wow, what a confusing thing :-) You are right and it's the sorting. Reason is that is uses the distance of the camera to the center of the polygons. Even with orthographic camera (where this is not correct). Thought it also shows the trouble in this approach when using another camera (and setting it for example to z = -500). Sorting in Irrlicht for orthographic cameras is definitely wrong. But I wonder if it would generally make more sense to use the distance to the camera-plane instead of to the camera position. Can't really think of a situation where changing that would be worse (maybe a little slower calculation...).

Workaround ... use a larger z to separate your drawing planes. With orthographic camera that shouldn't matter.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Thank you very much for your reply and for the investigation! I'll try your workaround!

I checked the Irrlicht Feature requests, and I found those two requests that may be related with the problem :
Is the sorting "issue" categorized as a bug? Will it be addressed in a future release? When could I expect such a release?

Sorry if it looks like I'm putting undue pressure here, I'm really not. This issue is serious for us, as the Irrlicht wrapper I'm currently coding is going to be used by programmers who have very limited 3D experience, and it may not be obvious to them why they need to separate the Z values so much. But I also realize that using Irrlicht as a 2D engine is not the common use case, and something important for us might not be important at all for the community. So I'm trying to assess what would be the best course of action for us : leave it like that and wait for an Irrlicht release (if a new release is just around the corner), reimplement createDevice to use a custom derived version of CxxxDriver that sorts nodes based on z-value (harder to maintain if I wish to keep up with Irrlicht's releases), or implement a "Z-Value Manager" that wraps the creation of "drawing planes" to prevent our 2D programmers from running in the issue.

Unfortunately, I don't feel confident enough in my knowledge of 3D in general, and in Irrlicht's architecture in particular, to post a patch myself. :(
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

Yeah, I've been thinking about that sorting on the weekend. Don't know yet if I'll work on that. I would like to add it, but I'm currently not able to work much. And it's not on top of my todo (bunch of other bugs, some of which I already spend some time).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

Hi again.

I thought of a way to correct this problem. CuteAlien, can you validate I'm not breaking something else with my "patch"?

In the base class of all the classes I'm creating, I reimplemented the getAbsoluteTransformation() like this :

Code: Select all

const matrix4& TMadLight2DObject::getAbsoluteTransformation() const
{
  static matrix4 fixedDistance;
 
  fixedDistance = AbsoluteTransformation;
  fixedDistance[14] *= 20.0f; // or 100.0f, I haven't decided yet.
  return fixedDistance;
}
 
Since I'm using an ortho camera, the distance shouldn't matter anyway, so I figured I could "fudge" the transformation matrix. Of course, I cranked up the orthographic field of view accordingly.

That's the best way I found to correct the problem in a non-intrusive way. Is that okay?
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

Can't you rather set the real position that far apart? It's hard to tell if there are any situations where this might mess up things (collisions maybe...).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: Strange circle with billboard and ortho camera.

Post by MartinVee »

I'll test it, thought I doubt we'll be using the collision in Irrlicht.

Like I hinted previously, I'm writing a wrapper (a bunch of classes, really) to be able to use Irrlicht like a 2D engine. The programmers that are going to work with it have experience in 2D programming with a basic layer engine (that was developped in-house for a custom platform). That engine didn't support collision. I'm only trying to create a wrapper that will cash-in on those programmers' skillset. I'm reproducing the way the layers worked in our previous engine so the learning curve isn't too steep for them. And once Irrlicht is integrated in our code base, it'll be easier to transition to 3D development over a long course of time.

My first thought was to do as you say, and ask them to have Z-value farther apart, but that's confusing, and I can understand why.

I know it's far from ideal ; it's an ugly patch that might come back and bite me later. I understand why this bug is not a priority though, and I do really appreciate the amount of time you put in trying to help me and understand the problem. But right now I really need a solution that work seamlessly with what I'm trying to achieve, and that's the best I can do. Unfortunately, I'm not skilled enough (yet) to submit a patch to correct the problem, or I would gladly do it.
CuteAlien
Admin
Posts: 9746
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Strange circle with billboard and ortho camera.

Post by CuteAlien »

That bug has a pretty high priority (I have cases in one of my own projects where it also shows up) and you made a great test-case. I just couldn't code last few weekends so my todo got even more out of control than usual :-) The main problem here right now is that I can't decide yet to do a tiny fix here or to spend more work and allow custom sorting from user code (which has been requested since a long time). And with x-mas coming up ... uhm... I guess it'll probably be January before I can take a look at this.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply