Applying Materials in C++

I’ve been trying to apply a non-textured white unlit material.
I think I’m either not setting or not applying it correctly.
I’ve tried clearing the materials and textures on the node after loading the model.
Here is the code:

Material whiteMat;
whiteMat.set_ambient(LColor(1, 1, 1, 1));
    // Also tried that with "models/box"
    NodePath node = window->load_model(framework->get_models(), "models/misc/rgbCube");
node.clear_texture(); // Doesn't seem to do anything
node.set_material(material, 1);

Any help would be appreciated.

Hi, welcome to the community!

Firstly, clear_texture() only clears a texture specification on the current node, not on any child nodes. You want to call set_texture_off(1) to override any texture specification on lower nodes (with an override value lower than 1) as well.

Secondly, set_material takes a pointer, so you should do:

Material *whiteMat = new Material;
whiteMat->set_ambient(LColor(1, 1, 1, 1));
node.set_material(whiteMat, 1);

Thirdly, the ambient color only affects ambient light conditions. You probably want to set the diffuse color and the ambient color both. The default, with no diffuse color specified, is to take the diffuse color from the vertex colors, if present.

Fourthly, materials are only respected if lights are present, so you need to apply lighting if you need to use a material.

Thanks that works great!

I also don’t know what happened to the & sign when I copied the code :stuck_out_tongue:.

This is my code now:

AmbientLight light("ambient light");
light.set_color(LColor(1.0f, 1.0f, 1.0f, 1));
NodePath lightNode = window->get_render().attach_new_node(&light);

Material mat("some material");
mat.set_ambient(LColor(0, 1, 0, 1)); // ambient light => ambient (green) colour
NodePath box = window->load_model(framework.get_models(), "models/box");
box.set_material(&mat, 1); 

To do the equivalent with the diffuse colour, just change set_ambient to set_diffuse and replace the ambient light with a point/spot/directional light :slight_smile:.

I don’t suggest doing that; you are creating these Material and AmbientLight objects on the stack, and therefore as soon as the function you’re executing that ends, these objects get destructed, and these nodes will be left holding a pointer to freed memory, which may cause a crash.

You should create them on the heap instead, using Panda’s smart reference counting, like so:

PT(AmbientLight) light = new AmbientLight("ambient light");
PT(Material) mat = new Material("some material");

This caveat does not apply to NodePath since a NodePath is merely a handle to a node, not the node itnself.

Correct me if I’m wrong, but this shouldn’t be a problem if I create them inside of main. Also, isn’t accessing the memory from the stack faster than from the heap?

Maybe not in this case (assuming you also keep the node around for the entire application’s lifetime), but then at some point you will eventually want to restructure your code as your application gets more complex, or do things like removing the node or replacing its material, and following best practices in this regard will make it easier to do so without causing crashes.

Allocating is faster, accessing is not really particularly faster in this case. But this is one-time initialization and so it doesn’t make a measurable difference.

Ok thank you for clarifying that :grin:
Are there any up to date examples of using C++ with Panda3D in a full project? Hopefully something more advanced than the Panda Hello World example from the manual :stuck_out_tongue: