Tue, Apr 16, 11:08 AM CDT

Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Mar 19 1:03 pm)

We now have a ProPack Section in the Poser FreeStuff.
Check out the new Poser Python Wish List thread. If you have an idea for a script, jot it down and maybe someone can write it. If you're looking to write a script, check out this thread for useful suggestions.

Also, check out the official Python site for interpreters, sample code, applications, cool links and debuggers. This is THE central site for Python.

You can now attach text files to your posts to pass around scripts. Just attach the script as a txt file like you would a jpg or gif. Since the forum will use a random name for the file in the link, you should give instructions on what the file name should be and where to install it. Its a good idea to usually put that info right in the script file as well.

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



Subject: HDR Background


adp001 ( ) posted Sat, 08 May 2021 at 9:52 AM · edited Sat, 06 April 2024 at 11:43 AM

Creating a HDR Background and a Grouping Object to rotate it.

from __future__ import print_function
import sys, os, math, wx

try:
    import poser
except ImportError:
    # Not required while inside Poser Python, but very helpfull for external editors.
    # See https://adp.spdns.org
    from PoserLibs import POSER_FAKE as poser

if sys.version_info.major > 2:
    # Python 3 (Poser 12 and above)
    map = lambda a, b: [a(_b) for _b in b]
    basestring = str
else:
    range = xrange

SCENE = poser.Scene()
P_ROTS = poser.kParmCodeXROT, poser.kParmCodeYROT, poser.kParmCodeZROT
ROTOBJ_COLOR = (200, 100, 120)


def do_rot(parm, newvalue):
    assert isinstance(parm, poser.ParmType)
    shdr = SCENE.BackgroundShaderTree()
    node = [n for n in shdr.Nodes() if n.Type() == "ccl_Mapping"]
    if not node:
        return
    idx = P_ROTS.index(parm.TypeCode())
    vec = node[0].InputByInternalName("Rotation").Value()
    vec[idx] = math.radians(newvalue)

    return newvalue


def get_node(shader, nodetype, name=None):
    """:rtype: poser.ShaderNodeType"""
    for node in shader.Nodes():
        if node.Type() == nodetype:
            if name and node.Name() != name:
                continue
            return node
    return None


def get_or_create_node(shader, nodetype, name=None):
    node = get_node(shader, nodetype, name)
    if node is None:
        node = shader.CreateNode(nodetype)
    return node


def get_input(node, inp_name):
    """:rtype: poser.ShaderNodeInputType"""
    for inp in node.Inputs():
        if inp.Name() == inp_name:
            return inp
    return None


def delete_actor(iname):
    try:
        SCENE.ActorByInternalName(iname).Delete()
    except poser.error:
        pass


def create_background(imagename=None):
    SCENE.Actor("GROUND").SetVisible(0)
    shdr = SCENE.BackgroundShaderTree()
    bkgrnd = get_or_create_node(shdr, poser.kNodeTypeCodeBACKGROUND)
    get_input(bkgrnd, "Color").SetColor(1.0, 1.0, 1.0)
    get_input(bkgrnd, "Specular_Color").SetColor(0.0, 0.0, 0.0)
    get_input(bkgrnd, "Diffuse_Color").SetColor(1.0, 1.0, 1.0)
    get_input(bkgrnd, "Cast_Light").SetFloat(1)

    hsv = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesHSV)
    img = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesENVIRONMENTTEXTURE)
    mapping = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
    tcoords = get_or_create_node(shdr, poser.kNodeTypeCodeCyclesTEXTURECOORDINATE)

    shdr.AttachTreeNodes(bkgrnd, "Color", hsv)
    shdr.AttachTreeNodes(hsv, "Color", img)
    shdr.AttachTreeNodes(img, "Vector", mapping)
    shdr.AttachTreeNodes(mapping, "Vector", tcoords)

    if isinstance(imagename, basestring):
        get_input(img, "Image").SetString(imagename)

    shdr.UpdatePreview()


def create_rotobj():
    def _cb_intens(parm, value):
        node = get_node(SCENE.BackgroundShaderTree(), poser.kNodeTypeCodeCyclesHSV)
        if node:
            get_input(node, "Value").SetFloat(value)
        return value

    def _rot_set(inp, xyz, v):
        vec = list(inp.Value())
        vec[xyz] = v
        inp.SetColor(*vec)

    def _cb_xrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 0, math.radians(value))
        return value

    def _cb_yrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 1, math.radians(value))
        return value

    def _cb_zrot(parm, value):
        shdr = SCENE.BackgroundShaderTree()
        node = get_node(shdr, poser.kNodeTypeCodeCyclesMAPPING)
        if node:
            _rot_set(get_input(node, "Rotation"), 2, math.radians(value))
        return value

    try:
        obj = SCENE.Actor("WorldRotation")
    except poser.error:
        obj = SCENE.CreateGrouping()
        obj.SetName("WorldRotation")
        obj.SetDisplayStyle(poser.kDisplayCodeEDGESONLY)

        shdr = obj.Material("Preview").ShaderTree()
        r, g, b = map(lambda n: 1.0 / 255.0 * n, ROTOBJ_COLOR)
        shdr.Node(0).Input(0).SetColor(r, g, b)
        shdr.UpdatePreview()

    parmnames = [p.Name() for p in obj.Parameters()]
    for parmname, cb, pp in [
                         ("Z Rotation", _cb_zrot, (None, None, 0, None)),
                         ("Y Rotation", _cb_yrot, (None, None, 0, 1)),
                         ("X Rotation", _cb_xrot, (None, None, 0, 1)),
                         ("Intensity", _cb_intens, (0, 2, 1, 1))
                         ]:
        if parmname not in parmnames:
            p = obj.CreateValueParameter(parmname)
            min_v, max_v, default_v, sens = pp
            if min_v:
                p.SetMinValue(0)
            if max_v:
                p.SetMaxValue(2)
            if default_v:
                p.SetValue(1)
            if min_v or max_v:
                p.SetForceLimits(1)
                p.ApplyLimits()
            if sens:
                p.SetSensitivity(sens)
            p.SetUpdateCallback(cb)
    return obj


if __name__ == "__main__":
    filename = None
    with wx.FileDialog(None, "Select Background Image") as dlg:
        if dlg.ShowModal() == wx.ID_OK:
            filename = os.path.join(dlg.GetPath())
    create_background(filename)
    obj = create_rotobj()
    SCENE.DrawAll()

Bildschirmfoto vom 2021-05-08 16-51-28.png




adp001 ( ) posted Sat, 08 May 2021 at 10:02 AM · edited Sat, 08 May 2021 at 10:02 AM

First thing the script does is presenting a dialog to select a HDR Image. If you have already an Environment Image in your background, you can simply abort this dialog and your old image is not touched.

If you select a new one, it may happen that Poser gets the filename but doesn't show the image. In this case you have to go to the materialroom and select the image "by hand".




adp001 ( ) posted Sat, 08 May 2021 at 10:03 AM

XYX Rotation is in degrees, not radian.




adp001 ( ) posted Sat, 08 May 2021 at 10:26 AM

Small update: Intensity was not correct.

Download update from my website: https://adp.spdns.org/#WorldRotation




adp001 ( ) posted Sat, 08 May 2021 at 11:50 AM · edited Sat, 08 May 2021 at 11:51 AM

After a second thought and some playing around, I made another version based on a Grouping Object. But now the groupings Rotation-, Scale- and Translation Dials are used. All of them. And this time I named the Grouping Object "WorldBackground".

Download this version here: https://adp.spdns.org/#WorldRotation2




infinity10 ( ) posted Sun, 09 May 2021 at 3:42 AM
Online Now!

Interesting. Thanks.

Eternal Hobbyist

 


adp001 ( ) posted Sun, 09 May 2021 at 9:20 AM

Welcome.

Beside of rotation I use scale depending on the camera zoom. X scale should alsways be negative to avoid the mirror effect.




adp001 ( ) posted Sun, 09 May 2021 at 10:57 AM

WorldRotation2 updated. X-scale does automatic mirroring now.

Download updated and bugfixed version here: https://adp.spdns.org/#WorldRotation2




adp001 ( ) posted Sun, 09 May 2021 at 2:41 PM · edited Sun, 09 May 2021 at 2:41 PM

Another update: Switch added to turn light on/off.

All lights in the scene are switched off or on but not "Image Based lights" (IBL). IBL is ignored by Superfly. So, if you need a permanent "edit light", use IBL's.

Download updated version here: https://adp.spdns.org/#WorldRotation2




adp001 ( ) posted Sun, 09 May 2021 at 2:56 PM

My Poser 11 does not attach the selected image to the material. The filename is attached to the material, but the image is not shown. I have to attach the image from the Materialeditor (Poser finds the path and shows the image I selected previously).

Is this only my installation (I use windows in an virtual environment) or should I better remove the image selection when the script is started?




adp001 ( ) posted Mon, 10 May 2021 at 7:16 AM

Another updated/extended version.

Download: https://adp.spdns.org/#BackgroundHDR

Added: Brightness/contrast. Added: Hide Scene objects. Bugfixes.

Cycles Brightness/Contrast shader is used instead of HSV. You have to play with the numbers for this shader. Attention: If you reduce the brightness, you may want to reduce the contrast as well. I didn't find a fitting formular to automate this. Maybe someone has an idea?

Hide/Show scene object can be used to get faster previews while working with the background. All objects in the scene are switched invisible. Before that the visible/invisible state of each object is saved and later restored.

Light On/Off shwitches all lights except IBL.

The script won't ask for a background image anymore. You have to set it by yourself (because it didn't work for me).




adp001 ( ) posted Mon, 10 May 2021 at 7:20 AM

I changed the scripts name to "BackgroundHDR.py" in case someone wants the previous version.

I couldn't test it, but the script should work in Poser 11 and 12.




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.