Irrlicht 1.4 - Material on custom scene node

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Carnafex
Posts: 15
Joined: Wed Sep 05, 2007 1:32 am
Location: Sydney, Australia

Irrlicht 1.4 - Material on custom scene node

Post by Carnafex »

Hi everyone!

I was in the process of updating my program from version 1.3.1 to 1.4 of irrlicht, and I ran into a little problem with my custom scene node.
The scene node is simply a quad with a texture on top (which I use for background elements in my scene.) In 1.3.1, the textures worked as normal. However, once I updated to 1.4, the texture no longer works, and only a white quad is rendered.
All other parts work fine. It's the right size, is animated correctly, etc. It's simply the texture thats gone wonky.

Here's the code for the quad:

Code: Select all

class CScenePlane : public scene::ISceneNode
{
	core::aabbox3d<f32> Box;
	video::S3DVertex Vertices[4];
	video::SMaterial Material;
	
	public:

	CScenePlane(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) : scene::ISceneNode(parent, mgr, id)
	{
		Material.Wireframe = false;
		Material.Lighting = false;

		Vertices[0] = video::S3DVertex(-10,0,-10, 0,0,1, video::SColor(255,255,255,255), 1, 0); 
		Vertices[1] = video::S3DVertex( 10,0,-10, 0,0,1, video::SColor(255,255,255,255), 1, 1); 
		Vertices[2] = video::S3DVertex( 10,0, 10, 0,0,1, video::SColor(255,255,255,255), 0, 1); 
		Vertices[3] = video::S3DVertex(-10,0, 10, 0,0,1, video::SColor(255,255,255,255), 0, 0);
	
		Box.reset(Vertices[0].Pos);
		for (s32 i=1; i<4; ++i)
			Box.addInternalPoint(Vertices[i].Pos);
	}

	virtual void OnRegisterSceneNode()
	{
		if (IsVisible)
			SceneManager->registerNodeForRendering(this);

		ISceneNode::OnRegisterSceneNode();
	}

   virtual void render() 
   { 
      u16 indices[] = { 0,2,1, 2,0,3 }; 
      video::IVideoDriver* driver = SceneManager->getVideoDriver(); 

      driver->setMaterial(Material); 
      driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); 
      driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 2); 
   } 

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

   virtual u32 getMaterialCount() { return 1; } 

   virtual SMaterial& getMaterial(u32 i) { return Material; }
};
I'm not sure what might be causing the problem, so I decided to post here and see if someone with a bit more knowledge of Irrlicht might be able to help!

If anyone might know what the solution to fix this is, I would really appreciate it!
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

For apply texture to material do You use "setMaterial" function? You can try:

Code: Select all

Node->getMaterial(0).TextureLayer[0].Texture = MyTexture;
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
shogun
Posts: 162
Joined: Wed Sep 05, 2007 11:02 am
Location: inside

Post by shogun »

virtual u32 getMaterialCount() const { return 1; }
Carnafex
Posts: 15
Joined: Wed Sep 05, 2007 1:32 am
Location: Sydney, Australia

Post by Carnafex »

Changing getMaterialCount() to const did the trick.
Thanks for the help!
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Hi,
I'm trying to port my DecalSceneNode to v1.4 and I think I have the same problem, but can't solve it !?!?! :shock:
I do exactly the same and getting the same result !!!
if I set the texture, the quad gets black, if I don't set the texture the quad uses the vertex color...

I also have no const behind getMaterialCount, but I thought this doesn't matter, because I set the material directly and not with the setMaterial functions...

after I found this thread I decided to give this const a try, as far as it seems to be exactly my problem... ;)
but if I declare getMaterialCount as const the test program crashes !?!?! :shock:

IDecalSceneNode.h:

Code: Select all

#ifndef __I_DECAL_SCENE_NODE_H_INCLUDED__
#define __I_DECAL_SCENE_NODE_H_INCLUDED__
#include "ISceneNode.h"
namespace irr{
namespace scene{

class IDecalSceneNode : public ISceneNode{
  public:
    IDecalSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, core::triangle3df tri,
    core::vector3df intersection, video::ITexture* image, float size):ISceneNode(parent, mgr) {}
    virtual void setLifeSpan(double seconds) = 0;
    virtual const core::dimension2d<f32>& getSize() = 0;
};

} // namespace scene
} // namespace irr
#endif
CDecalSceneNode.h:

Code: Select all

#ifndef __C_DECAL_SCENE_NODE_H_INCLUDED__
#define __C_DECAL_SCENE_NODE_H_INCLUDED__
#include "time.h"
#include "IDecalSceneNode.h"
#include "S3DVertex.h"
namespace irr{
namespace scene{

class CDecalSceneNode : public IDecalSceneNode{
  public:
    CDecalSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, core::triangle3df tri, core::vector3df intersection, video::ITexture* image, float size);
    virtual void setLifeSpan(double seconds);
    virtual void OnRegisterSceneNode();
    virtual void render();
    virtual const core::aabbox3d<f32>& getBoundingBox() const;
    virtual const core::dimension2d<f32>& getSize();
    virtual video::SMaterial& getMaterial(s32 i);

//    virtual u32 getMaterialCount()const; // <<< program crash
    virtual u32 getMaterialCount();

    virtual ESCENE_NODE_TYPE getType() { return ESNT_BILLBOARD; }

  private:
    time_t c_time;
    double lifeSpan;
    core::dimension2d<f32> Size;
    core::aabbox3d<f32> BBox;
    video::SMaterial Material;
    video::S3DVertex vertices[4];
    u16 indices[6];

};

} // namespace scene
} // namespace irr
#endif
CDecalSceneNode.cpp:

Code: Select all

#include "CDecalSceneNode.h"
#include "time.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ICameraSceneNode.h"
#include "os.h"
namespace irr{
namespace scene{

CDecalSceneNode::CDecalSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, core::triangle3df tri, core::vector3df intersection, video::ITexture* image, float size):IDecalSceneNode(parent, mgr, tri, intersection, image, size){
  #ifdef _DEBUG
  setDebugName("CDecalSceneNode");
  #endif
  time(&c_time);
  lifeSpan=0;
  // create quad
  core::vector3df pointA=tri.pointA;
  core::vector3df pointB=tri.pointB;
  core::vector3df pointC=tri.pointC;
  float posA=intersection.X;
  float posB=intersection.Y;
  float posC=intersection.Z;
  core::vector3df trinormal=tri.getNormal();
  float dotcorrection=1;
  float basesize=size/2;
  trinormal=trinormal.normalize();
  core::line3d<f32> line1(pointA, pointB);
  core::vector3df v1 = line1.getVector().normalize();
  core::vector3df v2 = line1.getClosestPoint( pointC );
  core::line3d<f32> line2(v2,pointC);
  core::vector3df v3 = line2.getVector().normalize();
  core::vector3df squarepA=(v1*-basesize)+trinormal*dotcorrection+(v3*-basesize);
  core::vector3df squarepB=squarepA+(v1*basesize*2);
  core::vector3df squarepC=squarepA+(v1*basesize*2)+(v3*basesize*2);
  core::vector3df squarepD=squarepA+(v3*basesize*2);
  squarepA=squarepA+core::vector3df(posA,posB,posC);
  squarepB=squarepB+core::vector3df(posA,posB,posC);
  squarepC=squarepC+core::vector3df(posA,posB,posC);
  squarepD=squarepD+core::vector3df(posA,posB,posC);
  vertices[0] = video::S3DVertex(squarepA.X,squarepA.Y,squarepA.Z, 1,0,0,video::SColor(255,255,255,255),1,0);
  vertices[1] = video::S3DVertex(squarepB.X,squarepB.Y,squarepB.Z, 1,0,0,video::SColor(255,255,255,255),1,1);
  vertices[2] = video::S3DVertex(squarepC.X,squarepC.Y,squarepC.Z, 1,0,0,video::SColor(255,255,255,255),0,1);
  vertices[3] = video::S3DVertex(squarepD.X,squarepD.Y,squarepD.Z, 1,0,0,video::SColor(255,255,255,255),0,0);
  BBox.reset(vertices[0].Pos);
  for(s32 i=1; i<4; ++i) BBox.addInternalPoint(vertices[i].Pos);
  indices[0] = 0;
  indices[1] = 1;
  indices[2] = 2;
  indices[3] = 0;
  indices[4] = 2;
  indices[5] = 3;
  setAutomaticCulling(scene::EAC_BOX);
  // set material
  Material.Lighting = false;
  Material.ZBuffer = true;
  Material.ZWriteEnable = true;
  Material.BackfaceCulling = false;
  Material.Wireframe = false;
  Material.setTexture(0,image);
  //Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;


  //this->setMaterialFlag(video::EMF_LIGHTING, false);
  //this->setMaterialFlag(video::EMF_ZBUFFER, true);
  //this->setMaterialFlag(video::EMF_ZWRITE_ENABLE, true);
  //this->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);
  //this->setMaterialTexture(0, image );
}

void CDecalSceneNode::setLifeSpan(double seconds){
  lifeSpan = seconds;
}

void CDecalSceneNode::OnRegisterSceneNode(){
  if(lifeSpan>0){
    if(difftime(time(NULL),c_time) > lifeSpan)
      SceneManager->addToDeletionQueue(this);
  }
  if(IsVisible){
    SceneManager->registerNodeForRendering(this);
    ISceneNode::OnRegisterSceneNode();
  }
}

const core::dimension2d<f32>& CDecalSceneNode::getSize(){
  return Size;
}

void CDecalSceneNode::render(){
  video::IVideoDriver* driver = SceneManager->getVideoDriver();
  driver->setMaterial(Material);
  driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  driver->drawIndexedTriangleList(&vertices[0], 4, &indices[0], 2);
}

const core::aabbox3d<f32>& CDecalSceneNode::getBoundingBox() const{
  return BBox;
}

video::SMaterial& CDecalSceneNode::getMaterial(s32 i){
  return Material;
}

//u32 CDecalSceneNode::getMaterialCount()const{ // <<< program crash
u32 CDecalSceneNode::getMaterialCount(){
  return 1;
}

} // namespace scene
} // namespace irr
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

In case you don't declare the method const it won't be used internally in the engine. Hence, Irrlicht assumes your scene node has 0 materials (the default) and refuses to set up any material. That's why it stays black.
The crash is probably because you have to recompile your app.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

YEY! an opportunity to tell acki to rtfm/stfw, just like he does with the newbies !!! :lol:
Check the new beginners help FAQ thread ;), some of those methods are now const (getType), others have changed from s32 to u32 (getMaterial).
Also, it's not good that getType returns ESNT_BILLBOARD but the class doesn't inherit IBillboardSceneNode, because people might try to cast to a billboard node.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

hybrid wrote:In case you don't declare the method const it won't be used internally in the engine. Hence, Irrlicht assumes your scene node has 0 materials (the default) and refuses to set up any material. That's why it stays black.
yes, that's what I found out too when I tried to change it to const... ;)
bitplane wrote:YEY! an opportunity to tell acki to rtfm/stfw, just like he does with the newbies !!! :lol:
just to make you happy !!! :P
bitplane wrote:Check the new beginners help FAQ thread ;), some of those methods are now const (getType), others have changed from s32 to u32 (getMaterial).
well, I did, otherwise I probably didn't make this changes... ;)
well, unfortunately I overlooked the s32 in getMaterial... :oops:

thanks you both !!! :D
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Post Reply