Why is my scene node black? LIGHTING does not help.

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.
Post Reply
nighthawk
Posts: 16
Joined: Tue May 30, 2006 5:43 am

Why is my scene node black? LIGHTING does not help.

Post by nighthawk »

Hi guys,

I was playing with customized scene node to create a tetraeder with each face using a different texture. I put vertices into four mesh buffers and added indices and textures to each mesh buffer. in render() method, I asked the driver to draw each mesh buffers.

My problem is that the scene node is black and no texture is visible. I tried to set EMF_LIGHTING to false but the scene node was still black. I added a lighting scene node but it did not help a lot and the scene node was monochromic although it was lightened up a little bit. There was still no texture.

Can anybody give me a hint what went wrong in my code? I'll post my code as a reply.

Thanks a lot.
nighthawk
Posts: 16
Joined: Tue May 30, 2006 5:43 am

Post by nighthawk »

Here is my code. It's not very clean:( . I used MS Visual Studio.
---------------------------------------------------------------------------------------

#include "stdafx.h"
#include "irrlicht.h"

using namespace irr;
using namespace scene;
using namespace video;
using namespace core;
#pragma comment(lib, "Irrlicht.lib")


class MySceneNode : public scene::ISceneNode
{
aabbox3d<f32> Box;
S3DVertex Vertices[4];
SMaterial Material;
SMeshBuffer *Buffers[4];

public:
MySceneNode(ISceneNode *parent, ISceneManager *mgr, s32 id)
: ISceneNode(parent, mgr, id)
{
IVideoDriver* driver = mgr->getVideoDriver();

Material.Wireframe = false;
Material.Lighting = false;

Vertices[0] = S3DVertex(0,0,10, 1,1,0, SColor(255,0,255,255),0,1);
Vertices[1] = S3DVertex(10,0,-10, 1,0,0, SColor(255,255,0,255),1,1);
Vertices[2] = S3DVertex(0,20,0, 0,1,1, SColor(255,255,255,0),1,0);
Vertices[3] = S3DVertex(-10,0,-10, 0,0,1, SColor(255,0,255,255),0,0);

SMeshBuffer* mbBottom = new SMeshBuffer();
mbBottom->Vertices.push_back(Vertices[0]);
mbBottom->Vertices.push_back(Vertices[1]);
mbBottom->Vertices.push_back(Vertices[3]);
mbBottom->Indices.push_back(0);
mbBottom->Indices.push_back(2);
mbBottom->Indices.push_back(1);
mbBottom->Material.Texture1 = driver->getTexture("../../media/portal1.bmp");
mbBottom->Material.Lighting = true;
mbBottom->Material.EmissiveColor = SColor(124,38,97,189);
Buffers[0] = mbBottom;
Material.Texture1 = driver->getTexture("../../media/portal1.bmp");


SMeshBuffer* mbTop1 = new SMeshBuffer();
mbTop1->Vertices.push_back(Vertices[0]);
mbTop1->Vertices.push_back(Vertices[3]);
mbTop1->Vertices.push_back(Vertices[2]);
mbTop1->Indices.push_back(0);
mbTop1->Indices.push_back(2);
mbTop1->Indices.push_back(1);
mbTop1->Material.Texture1 = driver->getTexture("../../media/portal2.bmp");
mbTop1->Material.Lighting = true;
mbTop1->Material.EmissiveColor = SColor(124,38,97,189);
Buffers[1] = mbTop1;

SMeshBuffer* mbTop2 = new SMeshBuffer();
mbTop2->Vertices.push_back(Vertices[0]);
mbTop2->Vertices.push_back(Vertices[1]);
mbTop2->Vertices.push_back(Vertices[2]);
mbTop2->Indices.push_back(0);
mbTop2->Indices.push_back(1);
mbTop2->Indices.push_back(2);
mbTop2->Material.Lighting = true;
mbTop2->Material.Texture1 = driver->getTexture("../../media/portal3.bmp");
mbTop2->Material.EmissiveColor = SColor(124,38,97,189);
Buffers[2] = mbTop2;

SMeshBuffer* mbTop3 = new SMeshBuffer();
mbTop3->Vertices.push_back(Vertices[1]);
mbTop3->Vertices.push_back(Vertices[3]);
mbTop3->Vertices.push_back(Vertices[2]);
mbTop3->Indices.push_back(1);
mbTop3->Indices.push_back(2);
mbTop3->Indices.push_back(0);
mbTop3->Material.Texture1 = driver->getTexture("../../media/portal4.bmp");
mbTop3->Material.EmissiveColor = SColor(124,38,97,189);
Buffers[3] = mbTop3;

Box.reset(Vertices[0].Pos);
for(s32 i = 1; i < 4; ++i)
Box.addInternalPoint(Vertices.Pos);
}

~MySceneNode(){
for(int i = 0; i< sizeof Buffers / sizeof *Buffers; i++){
Buffers->drop();
}
}

virtual void OnPreRender()
{
if(IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnPreRender();
}

virtual void render()
{
IVideoDriver* driver = SceneManager->getVideoDriver();

for(int i = 0; i < 4; i++){
driver->drawMeshBuffer(Buffers);
}
driver->setTransform(ETS_WORLD, AbsoluteTransformation);
}

virtual const aabbox3d<f32>& getBoundingBox() const
{
return Box;
}

virtual s32 getMaterialCount()
{
return 1;
}

virtual SMaterial& getMaterial(s32 i)
{
return Material;
}

};

int _tmain(int argc, _TCHAR* argv[])
{
IrrlichtDevice *device = createDevice(EDT_OPENGL, dimension2d<s32>(640, 480), 16, false);
device->setWindowCaption(L"Pengfei's scene node");
IVideoDriver *driver = device->getVideoDriver();
ISceneManager *mgr = device->getSceneManager();
mgr->addCameraSceneNode(0, vector3df(0, -40, 0), vector3df(0,0,0));
MySceneNode *mySceneNode = new MySceneNode(mgr->getRootSceneNode(), mgr, 666);
mySceneNode->setMaterialFlag(EMF_LIGHTING, false);
// Add a light scene node, it does not work. So it is commented out.
//ILightSceneNode* lightSN = mgr->addLightSceneNode(0, vector3df(0,6,0), SColorf(123,89,234,123), 4, -1);
//mySceneNode->addChild(lightSN);
mySceneNode->drop();


ISceneNodeAnimator *anim = mgr->createRotationAnimator(vector3df(0.8f, 0, 0.8f));
mySceneNode->addAnimator(anim);
anim->drop();
while(device->run())
{
driver->beginScene(true, true, SColor(0, 100, 100, 100));
mgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Several things here...

The reason your node comes out all black is indeed caused by the lighting. You need to apply the material [and the world transform] before you render the geometry, like so...

Code: Select all

virtual void render() 
{ 
  IVideoDriver* driver = SceneManager->getVideoDriver(); 

  driver->setTransform(ETS_WORLD, AbsoluteTransformation); 

  for(int i = 0; i < 4; i++)
  { 
    driver->setMaterial(Buffers[i].Material);
    driver->drawMeshBuffer(Buffers[i]); 
  } 
} 
I guess you could consider this to be a bug because the drawMeshBuffer() method could very well just set the material for you, but if you check the code, it doesn't.

Your getMaterial() and getMaterialCount() methods should probably provide information on the materials used by each of the mesh buffers. You don't need to track a seperate material for your scene node either. The mesh buffers don't need to be allocated on the heap, and you really don't even need to be using mesh buffers for your simple scene node.

Travis
nighthawk
Posts: 16
Joined: Tue May 30, 2006 5:43 am

What is the rule to index vertices?

Post by nighthawk »

Hi vitek,

Sorry for my late response. My project at work sucked in most of my time this last week and I did not get time to work on Irrlicht.

Thank you for your reply. Your suggestion worked very well for me. I agree with you that it looks like that driver->drawMeshBuffer() has a bug in setting up materials.

I am trying to create very attractive scene nodes directly within Irrlicht (No 3DS :->). I use this simple scene node to test out how to create scene nodes with different textures for each face.

I have another question about how to set up indices for vertices in mesh buffers. In my code above, in each mesh buffer, there are only three vertices. To me, indices should not matter because of the limited number of vertices for each mesh buffer so long as each vertex is indexed. But I found actually the sequence of indices mattered.

In my code, I used

mbBottom->Indices.push_back(0);
mbBottom->Indices.push_back(2);
mbBottom->Indices.push_back(1);
........
mbTop1->Indices.push_back(0);
mbTop1->Indices.push_back(2);
mbTop1->Indices.push_back(1);
........
mbTop2->Indices.push_back(0);
mbTop2->Indices.push_back(1);
mbTop2->Indices.push_back(2);
.......
mbTop3->Indices.push_back(1);
mbTop3->Indices.push_back(2);
mbTop3->Indices.push_back(0);

This worked and the tetraeder was rendered perfectly.

But If I use the following:

mbBottom->Indices.push_back(0);
mbBottom->Indices.push_back(2);
mbBottom->Indices.push_back(1);
........
mbTop1->Indices.push_back(0);
mbTop1->Indices.push_back(2);
mbTop1->Indices.push_back(1);
........
mbTop2->Indices.push_back(0);
mbTop2->Indices.push_back(2);
mbTop2->Indices.push_back(1);
.......
mbTop3->Indices.push_back(0);
mbTop3->Indices.push_back(2);
mbTop3->Indices.push_back(1);

the tetraeder is not closed and one face is missing.

What is the problem with the second way to index vertices? Is there any rule that I should follow when creating indices?

Sorry for the long post. I just want to state my question clearly.

Thanks a lot and have a good weekend.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Yes, the winding order is important. If you look at the triangle from the outside, you index the vertices in anti-clockwise order.

Travis
Post Reply