I’m trying to get material data of a model at ray collision points. I’m currently using obj
files so I’m guessing the material data I’d get is this?
newmtl Material.005
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
I’m looking for material data in the collided ray, found a referance to material at rayHit.into_node.state.attribs
but in the pycharm debugger I couldn’t get any further…
Is that the way to get it? if not, is there any other way?
Also are there any benefits to using one model type or another? for example obj vs fbx
thanks!
Hmm… I’m not sure that collision geometry has a material. (Unless you’re colliding with visible geometry, of course.)
However, if I’m mistaken, or if you’re colliding with visible geometry, then I note that your output indicates that you have a “RenderState” object that contains at least one “MaterialAttrib”–see the manual page for these here and here, respectively.
So, you should be able to iterate over the attribs that you’ve found in the RenderState, and–I would suggest first checking that they are indeed MaterialAttribs and not other types of attrib–access the materials from those attribs.
Diving a little deeper into model formats, I found huge inconsistencies in obj formats in terms of relative material and texture path mapping (found myself fixing them in a text editor)
I finally settled on glft
format as it’s just a json holding all the model data including material info, which is exactly what I need.
so, in panda, using panda3d-glft
to load the model, I can take the name of the hit object and then trace it’s material inside the glft json
This is a workaround as I’d much prefer getting the material data from panda itself.
Plus, this solution doesn’t solve the case where texture UV index (or texture sample) is needed
Another approach might be using shader data but I don’t see how it can be done without building a ray tracer from scratch…
If anyone has a good solution, please do say so 
Thanks!
Hmm… Well, if the geoms in your collision-geometry have unique names, then you could perhaps use a dictionary to associate them with materials, or other objects that contain materials.
But… In your output above, you seem to have a MaterialAttrib. Why not access that?
I don’t know why but it’s empty… If you take a closer look at the screenshot I added, you’ll see it says <RenderState.attribs[].....
I think the empty parentheses mean an empty list, I can’t access it or anything that resembles material data
Just to check: Have you tried accessing it? I don’t think that the empty parentheses actually indicates an empty list.
For example, I just ran a test in a project of my own. Looking at the state of “render”, much as you’ve done with “rayHit”, I see the following:
<RenderState.attribs[] of S:(CullFaceAttrib RescaleNormalAttrib ShaderAttrib)>
When I actually examine one of the attribs–in this case the “ShaderAttrib” however, I see an actual attrib.
Note that in my case I have three types of attrib present: A “CullFaceAttrib”, a “RescaleNormalAttrib”, and a “ShaderAttrib”. In your case you have one attrib present: A “MaterialAttrib”.
Interesting… this would sound silly but mind showing me how you access them? 
I’m generally trying to look for material info anywhere within the ray hit object with pycharm’s debugger, and when i got to RenderState it was empty… maybe I just don’t know how to access it
I do see it should have some attributes
Indeed, PyCharm’s debugger does have difficulty in accessing the attribs so stored!
So, as to accessing said attribs:
Looking at the API’s entry on the “attribs” object, we see that it “[l]ooks for a RenderAttrib of the indicated type in the state”. This means that we’re essentially treating it like a dictionary: we need to have the relevant attrib-class available (i.e. imported), and then pass that into “attribs” as a key.
Importing “MaterialAttrib”
In code, it looks something like this, if I’m not much mistaken:
from panda3d.core import MaterialAttrib
And then, when we want to access such an attrib:
attrib = rayHit.intoNode.state.attribs[MaterialAttrib]
# Note that we're using the "MaterialAttrib" class itself
# as the key above!
if attrib is not None:
# Do whatever you want to do with the attrib.
In the debugger it’s similar, but a little more awkward if you’re not in a piece of code that already has access to the “MaterialAttrib” class, I believe.
First of all thank you very much! 
For some reason for gltf models I get
rayHit.into_node.state.attribs = <RenderState.attribs[] of S:(empty)>
.
Does that mean attribute location is model type dependant?
After snooping around some more what worked for me was
rayHit.into_node.get_geom_states()[0].attribs[MaterialAttrib]
I’ll head to the docs about the attributes to carry on from here
Thanks again!
I’m glad if I’ve helped! 
Honestly, I don’t know. It might depend on how the format or exporter handles such things, or the settings used on export, or what modelling package was used, or how the modeller set things up–or something else besides!
Without more information on your pipeline and processes, or files to examine, it’s hard to guess at the cause, I fear.
1 Like