IMeshbuffer::getMaterial()

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
ignorator
Posts: 13
Joined: Fri Sep 21, 2007 1:36 am

IMeshbuffer::getMaterial()

Post by ignorator »

im trying to reset some textures inside a IMesh but it doesn't work.
getMaterial() returns a copy of the Material and not a pointer?
how do i get a pointer to the Material?

Code: Select all

		irr::video::SMaterial& mat = mesh->getMeshBuffer(meshbuffer_id)->getMaterial();
		mat.Textures[1] = tex;
		mat.Textures[0] = tex;
greetings
ignorator
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

getMaterial returns a reference (just as you used). A reference is different to a copy, it's basically a better pointer if you want. So just use ut as you did and it will work.
ignorator
Posts: 13
Joined: Fri Sep 21, 2007 1:36 am

Post by ignorator »

well it doesnt work :(

cmeshbuffer.h:

Code: Select all

	//! returns the material of this meshbuffer
		virtual video::SMaterial& getMaterial()
		{
			return Material;
		}
i think it returns a copy of Material via the copyconstructor?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

No, given the code you provided, there is no copy made. Either you aren't getting the material for the mesh buffer you think you are [because meshbuffer_id is wrong], or you are doing something else wrong.

Code: Select all

// this is _not_ a copy of the mesh buffers material. the
// getMeshBuffer() method returns a reference, which is
// essentially a pointer that cannot be reassigned. you
// are explicitly copying the returned reference, so no
// copy will be made.
irr::video::SMaterial& mat = mesh->getMeshBuffer(meshbuffer_id)->getMaterial(); 

// you would get a copy if you wrote this. notice the
// missing &...
irR::video::SMaterial copy = mesh->getMeshBuffer(meshbuffer_id)->getMaterial();
If you are so sure that it is broken, write a short testcase to prove it.

Travis
ignorator
Posts: 13
Joined: Fri Sep 21, 2007 1:36 am

Post by ignorator »

ok here is my testcase

its pretty much the same as helloworld but without the animation:

Code: Select all

#include <irrlicht.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")
#endif


int main()
{

	IrrlichtDevice *device =
		createDevice( video::EDT_SOFTWARE, dimension2d<s32>(640, 480), 16,
			false, false, false, 0);

	device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");

	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();
	IGUIEnvironment* guienv = device->getGUIEnvironment();

	guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!",
		rect<int>(10,10,260,22), true);

	IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
	IMeshSceneNode* node = smgr->addMeshSceneNode( mesh->getMesh(0) );
	
	if (node)
	{
		node->setMaterialFlag(EMF_LIGHTING, false);
	}
	
	// *************************************************************************************
	// setting textures via MeshBuffer doesnt work:
	ITexture* tex = driver->getTexture("../../media/sydney.bmp");
	for (int i=0; i<mesh->getMesh(0)->getMeshBufferCount(); i++)
	{
		IMeshBuffer* buf = mesh->getMesh(0)->getMeshBuffer(i);
		SMaterial& mat = buf->getMaterial();
		mat.Textures[0] = tex;
		
	}
	// commenting out the following line instead works:
	// if (node) node->setMaterialTexture(0,tex);
	// **************************************************************************************

	
	
	smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
	while(device->run())
	{
		driver->beginScene(true, true, SColor(255,100,101,140));
		smgr->drawAll();
		guienv->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 »

This is because each mesh scene node optionally maintains a copy of the materials [see IMeshSceneNode::setReadOnlyMaterials()]. When you say node->setMaterialTexture() that modifies the copy held by that mesh scene node, and those are the materials used to render [by default].

When you modify the mesh buffer material via buf->getMaterial(), you are changing the materials in the source mesh. Since those materials aren't used to render default constructed mesh scene nodes, it will only take effect for mesh scene nodes created after you make that call.

You should either use node->setMaterialTexture() or node->getMaterial() if you want to modify the material for an individual mesh scene node that uses its own material copy, or you can use the technique you are currently using if you setReadOnlyMaterials(true).

Travis
ignorator
Posts: 13
Joined: Fri Sep 21, 2007 1:36 am

Post by ignorator »

Ah ok that explains it...

thank you :D
Post Reply