Notifications
Clear all

[Closed] Problem with getting material data

Hi,

For some reason I am having a problem using an “if” statement to get an objects material data.
can anybody tell me why this does not work:

 
$box01.material.diffuse = (color 255 255 255)
a = $box01.material.diffuse
 
if a == (color 255 255 255) do (print "it works")

If i type this into the listerner it returns: undefined.
I dont understand why this does not work, it works fine if i try and access $.material.diffuse.r??

Anybody??

11 Replies

Did you actually apply a material to the box first? Doing that runs the code fine for me.

yeh the object has a material on.

I started by using the openbitmap command to import a small bitmap image into the scene, the script just takes each pixel in the bitmap and creates a box in the scene and adds a standardmaterial too it that corasponds to the pixel colour.

Now all I want to do is get boxes with a certain color eg: (color 255 0 9) and do something to them.
So i am looping through all the boxes like this:

 
for i in allboxes do
(
if i.material.diffuse == (color 255 0 9) do (print "it works")
)
 

But this does seem to do anything!?? I have just tried opening a new scene and creating an object and assigning it a material from the material editor, if i do this i can select it and use:
if $.material.diffuse == (color 150 150 150) do (print “it works”) and it does work!!

I dont think there is a problem with the boxes material as all I have done is loop though the boxes and assigned them a standardmaterial:

 
for w = 1 to aa_w do 
(
pixelcol = pixel_line[w].r + pixel_line[w].g + pixel_line[w].b
newbox = box length:1 width:1 height:(pixelcol/50) pos: [w,-h,0]
newmat = standardmaterial diffuse: pixel_line[w]
newbox.material = newmat
)

[size=1][/size]

any ideas?

1 Reply
(@erilaz)
Joined: 11 months ago

Posts: 0

You might want to check out this older challenge, as it was centered around exactly what you’re doing:
http://forums.cgsociety.org/showthread.php?t=271753

As to the selection part i’m not sure why… I can have a go once i’m off work.

Maybe none of your boxes have that color in the diffuse. Just for debuging purposes, add a line to report what the code is doing outside of the if/do statement.


for i in allboxes do
(
[b]format "% diffuse color: %
" i i.material.diffuse[/b]
if i.material.diffuse == (color 255 0 9) do (print "it works")
)

Something that is not very obvious – the colors in Max are internally floats in the 0.0-1.0 range. The 0-255 colors you see are a print time representation of the internal values. So if you read and assigned some bitmap pixel to some object, that value might APPEAR to be some 8-bit color, but internally to be slightly off (because of decimal point imprecisions when converting the floating points to 255 range and back. Thus, you should use the CloseEnough() function provided in Max 2008 and higher (or in the Avguard Extensions before that) and check each component of the color one by one with some error threshold, or write your own function that takes the .R, .G and .B and looks if the result of the subtraction of the pairs is less than, say, 0.01 or something.

1 Reply
(@erilaz)
Joined: 11 months ago

Posts: 0

You know Bobo, sometimes I wish I didn’t have to say “Wow, I never knew that!” every single time you post.

That makes perfect sense! Thanks a lot for the help. Im using Max 7 at the moment so i dont have the closeenough() function but, I guess if i wanted to get round the problem i could tweek the colors of the boxes to make them whole numbers:

  
for i in allboxes do
(
new_r = ceil i.material.diffuse.r
new_g = ceil i.material.diffuse.g
new_b = ceil i.material.diffuse.b
 
i.material.diffuse.r = new_r
i.material.diffuse.g = new_g
i.material.diffuse.b = new_b
)

Il have a play with that. Cheers.

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

This might not help. I would rather do the tweaking when comparing, not when assigning. As I mentioned, when you assign a color of, say, color 127 43 151, the values stored internally are actually 0.498039 0.168627 0.592157 (the range from 0 to 255 is converted to 0-1 by dividing by 255.0 internally). As you can see, these numbers could cause problems because of decimal precision – accrding to MAXScript,

0.168627*255 = 42.9999 
 

but also according to MAXScript,

((color 127 43 151)/255.0)*255.0 = color 127 43 151

So the Green color is entered and shown as 43 in both cases, but the internal floating point value is ridiculously close to but not quite the same as 43…

So back to your example using the above “bad” number:


 $box01.material.diffuse = (color 127 43 151)
 (color 127 43 151)
 a = $box01.material.diffuse
 (color 127 43 151)
 if a == (color 127 43 151) do (print "it works")
 undefined
 if a as string == (color 127 43 151) as string do (print "it works")
 "it works"
 "it works"
 if abs(a.r-127.0)<0.001 AND abs(a.g-43.0)<0.001 AND abs(a.b-151.0)<0.001 do (print "it works")
 "it works"
 "it works"

So you can define a simple function like this:

fn closeEnoughColor colorA colorB precision:0.0001=
 (
 	abs (colorA.r-colorB.r) < precision AND \
 	abs (colorA.g-colorB.g) < precision AND \
 	abs (colorA.b-colorB.b) < precision AND \
 	abs (colorA.a-colorB.a) < precision
 )
 
 if closeEnoughColor a (color 127 43 151) do (print "it works")

The hacky way to do this without using the closeEnough function would be to do the comparison in a different space, as strings for example…


for i in allboxes do
(
if (i.material.diffuse as string) == ((color 255 0 9) as string) do (print "it works")
)
1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

Yep, if you look at my longer example above, I did that there, but did not comment on it because it is indeed a hack. But it works!

Thanks guys! i will have a go at doing the ‘proper’ way and if that doesnt work il use the hacky way!!

Cheers.