Tue, Apr 23, 1:43 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: Exporting posed and premorphed figure to modeller


adp001 ( ) posted Sat, 28 November 2020 at 2:59 AM · edited Mon, 22 April 2024 at 2:25 AM

I am currently working on transferring Poser models to Blender with as little effort as possible. For this purpose I'm using parts of "PoMo" (FullbodyMorphs_wx4.py) from the beginning of the year, besides some other scripts. Again I stumbled over the problem with the unused vertices that Poser does not remove from the "UniMesh".

Old thread: https://www.renderosity.com/rr/mod/forumpro/?thread_id=2941172

Now I was forced to take care of the problem and came up with the following, really simple solution:

    def used_list(_geom):
        """
        Return a list with 1 at positions of used vertices
        and 0 at unused vertices.
        """
        sets = _geom.Sets()
        ar = np.zeros(_geom.NumVertices(), np.int8)
        for poly in _geom.Polygons():
            start = poly.Start()
            numv = poly.NumVertices()
            for _idx in sets[start:start + numv]:
                ar[_idx] = 1
        return ar

The returned list is then used in the following function, which creates a crosslist:

    def crosslist(_used, _verts):
        cl = np.zeros(len(_verts), np.int32)
        not_empty_idx = 0
        for _idx in range(len(_verts)):
            if _used[_idx] != 0:
                cl[_idx] = not_empty_idx
                not_empty_idx += 1
        return cl

And the problem is solved. Quick and simple.

The new crosslist is used in the above mentioned script just like the previously created crosslist. But I don't save it anymore, I create it every time anew. The recalculation costs almost not noticeably more time.




adp001 ( ) posted Sat, 28 November 2020 at 3:16 AM · edited Sat, 28 November 2020 at 3:18 AM

Explanation:

Function used_list() creates an array of the length of the vertices in the geometry, initialized with zeros. Then the polygons returned by Poser in UniMesh are scanned and the array is set to 1 where a polygon actually uses a vertex. Not used indices are later skipped (vertices not written).

Function crosslist() now uses this list instead of checking vertices for [0.0, 0.0, 0.0]. This caused problems if a polygon actually used [0.0, 0.0, 0.0].




adp001 ( ) posted Sat, 28 November 2020 at 3:20 AM · edited Sat, 28 November 2020 at 3:22 AM

The core of an export function then looks like this:

        # exporting vertices
        used = used_list(vertices)
        for idx, vertex in enumerate(vertices):
            if used[idx] != 0:
                print("v {} {} {}".format(*vertex), file=fh)




adp001 ( ) posted Sat, 28 November 2020 at 3:27 AM

The "sets" must be rewritten like this:

        vertex_crosslist = crosslist(used, vertices)
        sets = geom.Sets()
        for idx in range(len(sets)):
            sets[idx] = vertex_crosslist[sets[idx]]




adp001 ( ) posted Sat, 28 November 2020 at 1:49 PM · edited Sat, 28 November 2020 at 1:50 PM

A complete script based on "Script Buttons" can be downloaded from:

https://adp.spdns.org/#ObjImExport

Script Buttons: https://www.renderosity.com/rr/mod/forumpro?thread_id=2954892




cantonesejim ( ) posted Fri, 01 January 2021 at 10:06 PM

I've been having an issue with the import figure button in Poser 12. It keeps erroring out when it tries to load the vertex data. Clipboard01.jpg


adp001 ( ) posted Sat, 02 January 2021 at 10:20 PM

As far as I can see, it seems like something is wrong with your file written from you modeller.

Can you import this file directly into Poser (with the "Import OBJ" function)?

For speed reasons the import function in the script does not check for problems or error conditions if only the file exists.

Script should run fine with P11 and P12. I didn't test P12, but an adapted form of the script in question (im_export.py) runs natively with Python 3.9.




cantonesejim ( ) posted Mon, 04 January 2021 at 4:40 PM

Thank you for the response, i checked the files and the vertex numbers add up and everything but i think it might be my poser install. Reinstalling and checking, if it doesn't make a difference i'll try in P11.


adp001 ( ) posted Mon, 23 August 2021 at 4:22 PM · edited Mon, 23 August 2021 at 4:32 PM

Updated.

Klick to Download.

Now able to deal with more then one figure in the scene. Each figure will have a seperate entry in the config file for pathes and filenames.

Bildschirmfoto vom 2021-08-23 23-30-46.png




bwldrd ( ) posted Mon, 23 August 2021 at 4:41 PM
Online Now!

TYVM :)

--------------------------------------------------------------------------------

Consider me insane if you wish, but is your reality any better?


adp001 ( ) posted Mon, 23 August 2021 at 5:26 PM

Forgotten to mention: If you used it before better delete the config file ("imex.config", same folder where your script is stored).




adp001 ( ) posted Mon, 23 August 2021 at 5:36 PM · edited Mon, 23 August 2021 at 5:39 PM

If you want to join several morphs into one full body morph, do the following:

  1. Dial in all morphs you need to shape your character.
  2. Uncheck "Silent Im-/Export".
  3. Export to "Figure_Morphed.obj".

Don't move your figure from now on!

  1. Set all morphs you want to combine (and later delete) to zero (don't use dials, insert a "0" to be sure it is really 0).
  2. Export as "Figure_Unmorphed.obj".
  3. Set a Morphname for the final morph.
  4. Import "Figure_Morphed.obj".

You may now delete all the morphs you have set to zero before.




adp001 ( ) posted Tue, 24 August 2021 at 3:54 PM

Update

Click to download

Supports Images, Bump and Transpareny for import into Blender better (mtl file).

Switch "Copy Imagefiles" on and off, because it makes no sense to copy the same images again and again to the same folder.




odf ( ) posted Tue, 24 August 2021 at 6:26 PM

That sounds great. I'll definitely try that out and study the code.

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


adp001 ( ) posted Fri, 10 September 2021 at 7:25 PM

New version with some updates.

Most widgets are now "ownerdrawn". Should run with Poser 11 and 12. Don't know how it works with iOS.

Bildschirmfoto vom 2021-09-11 02-22-24.png




adp001 ( ) posted Fri, 10 September 2021 at 7:30 PM

The morphname field can now automaticly increment (Checkbox autoincrement). If auto increment is enabled, two digits separated by a dot are appended to the name (if they are not already there). The number is incremented with each export.




adp001 ( ) posted Fri, 10 September 2021 at 7:45 PM

If "Export Groups" is enabled, Blender, for example, can automatically make vertex groups out of them.

"Do not always leave "X Center == 0" switched on. It makes sense if, for example, the center vertices of a head were moved during morphing (they are at X position 0). This happens easily when working with the Soft-Brush. I often use the soft brush on one half of the head (or chest) and then let Poser calculate the other half of the face/chest with the morph tool. This solves the problem of not being able to work symetrically with posed figures in Blender (and other modelers).

Translated with www.DeepL.com/Translator (free version)




adp001 ( ) posted Fri, 10 September 2021 at 7:49 PM

"Auto Sync" makes sure the figure in the script is always the one you have selected in Poser. Attention: Each figure has it's own morphname. If you change the figure, the morphname is also changed (switched to what you used before).




adp001 ( ) posted Sat, 11 September 2021 at 4:49 AM · edited Sat, 11 September 2021 at 4:51 AM

How to install:

The script consists of a main script ("Run.py") and a folder containing the required script parts to be loaded ("local_libs"). Create a separate folder for the script.Mine is called: "IM-EXporter". Unpack the ZIP file into this folder. From Poser you can then:

  1. start the script "Run.py" via Posers filemenu "File->Run Python Script...", or
  2. add "Run.py" to the file "/Runtime/Python/poserScripts/mainButtons.py" and add the Poser Python script buttons (my preferred method).

Path structure:

IM-EXporter
....local_libs
........__init__.py
........im_export.py
........wxPrepare.py
........WXTools.py
....Run.py

im_export.py contains anything to export a model and import a morph. The script strictly separates between UI part and the part that does the actual work. The result is that the import and export functions can be executed stand alone without any restrictions. And so of course can be used in your own script via "include".

wxPrePare.py contains functions that allows the script to work with both wxPython from Poser11 and Poser12 (i.e. Python 2 and Python 3).

WXTools.py contains wxPython functions and recreations of some standard controls ("ownerdrawn").




odf ( ) posted Sat, 11 September 2021 at 5:27 AM

adp001 posted at 5:25AM Sat, 11 September 2021 - #4427160

How to install:

Thanks! I was going to ask about that, not having done anything with Poser Python for a decade. Also this looks like a nice demo on how to load local libs in scripts. If I don't get too distracted by other things, I'll give this a try tomorrow.

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


odf ( ) posted Sat, 11 September 2021 at 10:55 PM

Hey adp001, is it possible that you packaged an outdated Run.py with the latest version? It's trying to read the IsChecked property of a CheckboxCtrl, which only has IsSelected. Also it seems to register native checkbox callbacks that CheckboxCtril does not have. I have less than zero knowledge of wx, though, so I may be completely misunderstanding something.

I managed to get the script to export a mesh with a morph on it, but none of the various option buttons seemed to do anything.

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


odf ( ) posted Sat, 11 September 2021 at 11:04 PM · edited Sat, 11 September 2021 at 11:11 PM

Ah, never mind, I wasn't seeing the complete interface. Looks like it's all working after my little tweaks.

ETA: Oh, "Import Morph" only seems to create a master channel with no dependencies. What am I doing wrong?

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


adp001 ( ) posted Sun, 12 September 2021 at 8:49 AM

odf posted at 8:42AM Sun, 12 September 2021 - #4427212

Ah, never mind, I wasn't seeing the complete interface. Looks like it's all working after my little tweaks.

ETA: Oh, "Import Morph" only seems to create a master channel with no dependencies. What am I doing wrong?

Shouldn't be empty. Only if there is nothing :)

The script checks for empty morphs and skips a morph if no deltas are created.

I tested it some minutes ago with a fresh figure. But to be sure I repacked anything so it reflects the newest changes also (added the current filenames in the tooltips for Ex-/Import; helps if "silent mode" is on). Just re-download please.




adp001 ( ) posted Sun, 12 September 2021 at 8:52 AM

If it still does not work for you, there is a small chance that P12 does something I didn't catch. But I'm sure we can find out what goes wrong.




adp001 ( ) posted Sun, 12 September 2021 at 8:54 AM

odf posted at 8:53AM Sun, 12 September 2021 - #4427212

ETA: Oh, "Import Morph" only seems to create a master channel with no dependencies. What am I doing wrong?

If you import the same obj file you have exported, than the result is zero and no morphs are created :)




odf ( ) posted Sun, 12 September 2021 at 5:49 PM

adp001 posted at 5:47PM Sun, 12 September 2021 - #4427226

odf posted at 8:53AM Sun, 12 September 2021 - #4427212

ETA: Oh, "Import Morph" only seems to create a master channel with no dependencies. What am I doing wrong?

If you import the same obj file you have exported, than the result is zero and no morphs are created :)

Maybe I'm not understanding the concept correctly. I apply some morphs to my figure, export, check in Blender that the morphs have been applied, set all morphs back to zero, import the OBJ that I've previously exported. That's not enough?

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


odf ( ) posted Sun, 12 September 2021 at 7:07 PM

Okay, turns out the only thing I really needed to change (on Poser 12.0.500) was the import wxPrepare in WXTools.py to import local_libs.wxPrepare. When loading the script I get an error complaining about a checkbox event with no object that I ignore, then the GUI for the tool appears and I only have to move it to a spot where I can see everything.

I have now managed to import a morph from an OBJ file using the tool. Do I understand correctly that I have to export the unmorphed figure each time directly before I import a new morph? Why is that necessary? I'm assuming some weirdness of the Poser interface?

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


adp001 ( ) posted Sun, 12 September 2021 at 8:03 PM · edited Sun, 12 September 2021 at 8:04 PM

odf posted at 7:11PM Sun, 12 September 2021 - #4427269

Okay, turns out the only thing I really needed to change (on Poser 12.0.500) was the import wxPrepare in WXTools.py to import local_libs.wxPrepare.

Ups! Yes, Python 12 has different import logic. But I thought I catched that.... Thanks for finding that out! Will change it tomorrow.

When loading the script I get an error complaining about a checkbox event with no object that I ignore, then the GUI for the tool appears and I only have to move it to a spot where I can see everything.

Problem is that if an error is generated while wxPython is active, Poser Python often can't recover. Silly things may happen then :)

I have now managed to import a morph from an OBJ file using the tool. Do I understand correctly that I have to export the unmorphed figure each time directly before I import a new morph? Why is that necessary? I'm assuming some weirdness of the Poser interface?

No. One export at the start of a session. Pre-morphed or posed. Exports are the Reference used in the modeller. What you add or subtract to this reference is your imported morph. It's late here in germany and I'm pretty tired. I think I do something like a manual the next days (online and "realtime", but in German).

The gist of it (in technical terms) is: morph = numpy.array(imported_vertices) - numpy.array(exported_vertices)




odf ( ) posted Sun, 12 September 2021 at 8:17 PM

adp001 posted at 8:11PM Sun, 12 September 2021 - #4427273

odf posted at 7:11PM Sun, 12 September 2021 - #4427269

Okay, turns out the only thing I really needed to change (on Poser 12.0.500) was the import wxPrepare in WXTools.py to import local_libs.wxPrepare.

Ups! Yes, Python 12 has different import logic. But I thought I catched that.... Thanks for finding that out! Will change it tomorrow.

When loading the script I get an error complaining about a checkbox event with no object that I ignore, then the GUI for the tool appears and I only have to move it to a spot where I can see everything.

Problem is that if an error is generated while wxPython is active, Poser Python often can't recover. Silly things may happen then :)

Just checking obj for None before trying to access its name field got rid of that error.

I have now managed to import a morph from an OBJ file using the tool. Do I understand correctly that I have to export the unmorphed figure each time directly before I import a new morph? Why is that necessary? I'm assuming some weirdness of the Poser interface?

No. One export at the start of a session. Pre-morphed or posed. Exports are the Reference used in the modeller. What you add or subtract to this reference is your imported morph. It's late here in germany and I'm pretty tired. I think I do something like a manual the next days (online and "realtime", but in German).

The gist of it (in technical terms) is: morph = numpy.array(imported_vertices) - numpy.array(exported_vertices)

Okay, that's making more sense to me now. It might be useful to make that more explicit in the interface. Maybe separate between reference and regular exports, display the file name of the reference export for the current figure, and if none exists either refuse to import morphs, issue a warning, or automatically create one.

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


adp001 ( ) posted Mon, 13 September 2021 at 11:38 PM · edited Mon, 13 September 2021 at 11:39 PM

Fixed.

I guess I didn't get enough sleep the last few days and created a pretty creative error.

Everything worked for me as long as I didn't restart Poser. That rarely happens here, because Windows with active Poser runs in a virtual machine on a separate server and is rarely shut down. Except when I brought Poser to a halt using Python :) And that's exactly what happened, after which this script here suddenly stopped working for me too and I got a chance to find the error.

Download the fixed version here.




RAMWorks ( ) posted Tue, 28 December 2021 at 1:51 PM

Thank you so much.  Wonderful that you've written python that runs in both Poser 11 and 12.  That's fantastic.  For the time being I'm doing all my content creation from Poser 11 and most of the scripts that are being written new these days are all for Poser 12 but I don't use it for production, YET!  

---Wolff On The Prowl---

My Store is HERE

My Freebies are HERE  


cantonesejim ( ) posted Fri, 04 November 2022 at 5:51 PM

any luck getting it to run on the latest version of 12? i keep getting this error:

  File "D:\Poser 12\Runtime\Python\poserScripts\IM_EXPORT\WxMain.py", line 33, in <module>

    reload(im_export)

NameError: name 'reload' is not defined

worked fine before upgrading


adp001 ( ) posted Tue, 08 November 2022 at 2:53 AM

Sorry for the late replay. I didn't get a notification.

I uploaded a version I'm using with P12 at the end of October:

https://adp.spdns.org/ImExporter_28102022.zip




adp001 ( ) posted Tue, 08 November 2022 at 3:57 AM

If you prefer to use the version you used before, mark line 33 as a comment (insert "#" as the first character of the line):

old: reload(im_export)
new: # reload(im_export)

Do so with all lines starting with "reload" if required.




adp001 ( ) posted Tue, 08 November 2022 at 3:59 AM

Updated my website. The latest version should work with P11 and P12.




bwldrd ( ) posted Tue, 08 November 2022 at 5:53 AM
Online Now!

Thank you very much.


--------------------------------------------------------------------------------

Consider me insane if you wish, but is your reality any better?


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.