Tue, Nov 19, 9:29 AM CST

Renderosity Forums / Poser Technical



Welcome to the Poser Technical Forum

Forum Moderators: Staff

Poser Technical F.A.Q (Last Updated: 2024 Nov 13 12:50 am)

Welcome to the Poser Technical Forum.

Where computer nerds can Pull out their slide rules and not get laughed at. Pocket protectors are not required. ;-)

This is the place you come to ask questions and share new ideas about using the internal file structure of Poser to push the program past it's normal limits.

New users are encouraged to read the FAQ sections here and on the Poser forum before asking questions.



Checkout the Renderosity MarketPlace - Your source for digital art content!



Subject: Better documentation on the Math_Functions node?


odf ( ) posted Sat, 19 October 2024 at 9:09 PM · edited Tue, 19 November 2024 at 9:27 AM

Hi all,

I'm working on a Python tool to help me create procedural textures for Poser. The idea is that I put a formula that depends on the UV position in a script, and the tool shows me a preview and writes out an .mt5 file that, when loaded into Poser, creates a compound node. A mini-matmatic, if you will.

Now for the preview to be correct, I need to understand what the relevant material room nodes do, and the one I'm focusing on for now is the Math_Functions node. The documentation of the various available functions in Math Nodes is not always very clear, and sometimes incorrect. For example, it says that for "log" the second input value is ignored, but in fact it is the base of the logarithm.

So, I'm wondering if there might be some other source of information on these functions with a bit more detail. It's not super-important because for most of them I can figure out how they work, but it would make things a tad easier.


-- I'm not mad at you, just Westphalian.


odf ( ) posted Sun, 20 October 2024 at 1:52 AM · edited Sun, 20 October 2024 at 1:56 AM

For reference, here's what I have so far (in Python, after import numpy as _np). Not super-confident about those last three, so I might dig for my texture baking kit for Poser and do a numerical comparison on top of the visual one. There may also be some edge cases I got wrong.


def bias(a, b):
    return a**(_np.log(b) / _np.log(0.5))


def gain(a, b):
    return _np.where(
        a < 0.5,
        bias(a * 2, 1 - b) / 2,
        1 - bias((1 - a) * 2, 1 - b) / 2
    )


op = {
    OpCode.Add: lambda a, b: a + b,
    OpCode.Subtract: lambda a, b: a - b,
    OpCode.Multiply: lambda a, b: a * b,
    OpCode.Divide: lambda a, b: a / b,
    OpCode.Sin: lambda a, _: _np.sin(a),
    OpCode.Cos: lambda a, _: _np.cos(a),
    OpCode.Tan: lambda a, _: _np.tan(a),
    OpCode.Sqrt: lambda a, _: _np.sqrt(a),
    OpCode.Pow: lambda a, b: a ** b,
    OpCode.Exp: lambda a, _: _np.exp(a),
    OpCode.Log: lambda a, b: _np.log(a) / _np.log(b),
    OpCode.Mod: lambda a, b: a % (_np.sign(a) * b),
    OpCode.Abs: lambda a, _: _np.abs(a),
    OpCode.Sign: lambda a, _: _np.sign(a),
    OpCode.Min: lambda a, b: _np.minimum(a, b),
    OpCode.Max: lambda a, b: _np.maximum(a, b),
    OpCode.Clamp: lambda a, _: _np.clip(a, 0, 1),
    OpCode.Ceil: lambda a, _: _np.ceil(a),
    OpCode.Floor: lambda a, _: _np.floor(a),
    OpCode.Round: lambda a, _: _np.round(a),
    OpCode.Step: lambda a, b: (a <= b).astype(_np.float32),
    OpCode.Smoothstep: lambda a, _: _np.clip(3 * a**2 - 2 * a**3, 0, 1),
    OpCode.Bias: bias,
    OpCode.Gain: gain,
}

-- I'm not mad at you, just Westphalian.


odf ( ) posted Sun, 20 October 2024 at 2:03 AM

I found two references for bias and gain on the interwebs that used different bias functions (Poser seems to go with the original one, not the faster alternative) and messed up the definition of the gain in two unique ways. I'm somewhat tempted to read the original paper, but I'm also way too lazy...

-- I'm not mad at you, just Westphalian.


bagginsbill ( ) posted Mon, 21 October 2024 at 2:10 PM · edited Mon, 21 October 2024 at 2:10 PM

I never found any Poser docs for the math behind any of the nodes. I reverse engineered everything.

Your bias is correct. You can actually verify this by hand, building a ** (log(b) / log(.5)) in nodes and then take THAT node, subtract with an actual math:bias node having the same inputs, then take the absolute value of that difference and multiply by 1000 and plug that into ambient_color. If there's any deviation it will show up as not black. Here I used U and V as my two inputs, and the lower four nodes do the explicit math. The upper two compare and amplify differences from the real Bias function.

Kic7Ormt9VlcalXCMBDc9Aw3G9r1ykioYrY84sQw.png


Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)


bagginsbill ( ) posted Mon, 21 October 2024 at 2:12 PM

I never saw the 2nd input to log do anything. I'm in Poser 12 and lower. What did you observe?


Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)


bagginsbill ( ) posted Mon, 21 October 2024 at 2:18 PM · edited Mon, 21 October 2024 at 2:23 PM

One of the craziest things I ever noticed was when studying the bias(U, V), the pattern is completely symmetrical about the diagonal. I looked more deeply at the math and found you can swap the inputs and get the same results:

a ** (log(b) / log(.5))

(e ** log(a)) ** (log(b) / log(.5))

e ** (log(a) * log(b) / log(.5))

e ** (log(b) * log(a) / log(.5))

(e ** log(b)) ** (log(a) / log(.5))

b ** (log(a) / log(.5))

All of these expressions have the same value.

I used "log" above but I really meant "ln". Depends on whether you're an engineer or scientist or mathematician. 


Renderosity forum reply notifications are wonky. If I read a follow-up in a thread, but I don't myself reply, then notifications no longer happen AT ALL on that thread. So if I seem to be ignoring a question, that's why. (Updated September 23, 2019)


odf ( ) posted Mon, 21 October 2024 at 7:06 PM
bagginsbill posted at 2:10 PM Mon, 21 October 2024 - #4490615

I never found any Poser docs for the math behind any of the nodes. I reverse engineered everything.

Your bias is correct. You can actually verify this by hand, building a ** (log(b) / log(.5)) in nodes and then take THAT node, subtract with an actual math:bias node having the same inputs, then take the absolute value of that difference and multiply by 1000 and plug that into ambient_color. If there's any deviation it will show up as not black. Here I used U and V as my two inputs, and the lower four nodes do the explicit math. The upper two compare and amplify differences from the real Bias function.

Excellent, thanks! I was considering something along those lines but somehow the multiplication at the end didn't occur to me. Brainworms, I swear.


-- I'm not mad at you, just Westphalian.


odf ( ) posted Mon, 21 October 2024 at 7:12 PM

bagginsbill posted at 2:12 PM Mon, 21 October 2024 - #4490616

I never saw the 2nd input to log do anything. I'm in Poser 12 and lower. What did you observe?

I'm getting this in Poser12, but only if SuperFly is selected as the renderer. For FireFly, it's the natural logarithm regardless of the second parameter. Preview and FireFly renders also produce the natural logarithm every time, while the SuperFly render reflects the image here.

SWK5gC5wU1zjC0TaiAZBTkvKPBzj7ouyCM5E4RoV.jpg

-- I'm not mad at you, just Westphalian.


odf ( ) posted Mon, 21 October 2024 at 7:17 PM
bagginsbill posted at 2:18 PM Mon, 21 October 2024 - #4490617

One of the craziest things I ever noticed was when studying the bias(U, V), the pattern is completely symmetrical about the diagonal. I looked more deeply at the math and found you can swap the inputs and get the same results:

Neat!


-- I'm not mad at you, just Westphalian.


odf ( ) posted Mon, 21 October 2024 at 8:28 PM
In Cycles, the logarithm takes a value and a base, so when emulating the old Poser math functions for SuperFly, they probably forgot about the second value being ignored.

-- I'm not mad at you, just Westphalian.


odf ( ) posted Tue, 22 October 2024 at 8:44 PM · edited Tue, 22 October 2024 at 8:45 PM

Probably not worth a separate post, but I got my little tool working. This Python code:

from pydeltamesh.makeTexture import *

u = Input(U(), "u")
v = Input(V(), "v")
mask = ((u - 0.5)**2 + (v - 0.5)**2).sqrt() < 0.5

mask.name = "mask"

with open("dot_mktx.mt5", "w") as fp:
    write_poser_file(fp, "dot", [mask])


produces this compound node (after loading from file):

yYyg0MnIGp6moaOfmVjOW6Sx9bUiGNIrhgpPwGOE.png

which can be used like this (for example):

QAfMHYhYcLIU8ykNL3UYN7aE80UNnqWIlQXXf286.png


If I add this to the Python script:

from PIL import Image
Image.fromarray(mask.data * 256).show()

I get shown a preview image. This is implemented very hackily at the moment, but easy to fix.

-- I'm not mad at you, just Westphalian.


odf ( ) posted Tue, 22 October 2024 at 8:47 PM

Now this also means I get to write formulas for testing my assumptions about how the Poser math functions work, rather than having to wire the test networks up by hand.

-- I'm not mad at you, just Westphalian.


Richard60 ( ) posted Tue, 12 November 2024 at 7:41 PM

If you are doing a lot of work in the material room this freebie may be useful as you can quickly check the values coming out of nodes.  That way you get a numeric reading of the output instead of just a color.

Value Viewer for Poser Super Fly

Poser 5, 6, 7, 8, Poser Pro 9 (2012), 10 (2014), 11, 12, 13


odf ( ) posted Wed, 13 November 2024 at 12:50 AM

Thanks, very neat!

-- I'm not mad at you, just Westphalian.


Privacy Notice

This site uses cookies to deliver the best experience. Our own cookies make user accounts and other features possible. Third-party cookies are used to display relevant ads and to analyze how Renderosity is used. By using our site, you acknowledge that you have read and understood our Terms of Service, including our Cookie Policy and our Privacy Policy.