More python help needed!



  • Hi,

    I'm trying to add a new poly (well a few) to an existing actor. I know the verts that will form the corners and I've sucessfully used CurrentActor().Geomtry().AddPolygon and the ploygons are indeed created, however they are not "attached" to the actor, I've called act.MarkGeomChanged() but still they are floating. I tried calling Weld() on the geometry object but that merged verts I didn't want it to. I'm guessing I really need to use AddGeneralMesh but I can't seem to work out what the parameters should be. What I'm after is the equivalent of selecting 4 existing verts in Blender and pressing F



  • @amethystpendant are you comfortable with posting your python script and reference to the actor you're working on?

    Unfortunately, none of the sample Python scripts use AddPolygon() to construct new geometries. I have a couple of scripts which do use it to construct new geometry, that then subsequently use Weld() (to create a separate bounding box for a figure) without collapsing non-coincident vertices.



  • @anomalaus Hi, more than happy to share! both the script and the obj are in the linked zip file it really is a bare bones! What it is trying to do is connect the under/overlaps of the blouse behind the top button (similar to the ones extant behind the other buttons. The polys definitely get created but just float and aren't connected to either each other or the existing object they are being added to. Any help appreciated!

    Amanda



  • @amethystpendant OK, sorry for the slow response due to reasons [Marvin: "Don't talk to me about life..."] ;-)

    First some tidy python tips so we're not making assumptions: within the makeButton1() method, geom gets used without assignment, since its assignment only occurred in the deflate_morph() method, which is never executed, so a copy of the geom=act.Geometry() needs to go at the top of makeButton1().

    Second, the BlouseOut.obj file doesn't contain a group called "Buttoned1", only a single usemtl Buttoned statement, so the script generates an error at the first p.IncludeInGroup("Buttoned1") line.

    error: No group bit for specified group name. No such group for this actor?
    

    I assume you had manually created a new group "Buttoned1" with the grouping tool to test this script. I've found that the grouping tool sometimes ignores groups if they contain no polys when it exits, so I created such a group and added all of the polys in the "Buttoned" material, which gives me the stitching for the other buttons.

    Unfortunately, despite there being no Weld() call, Poser went absolutely mental, screwing up vertices all over the blouse:

    0_1520262744043_Screen Shot 2018-03-06 at 1.58.24 am.png

    and then proceeded to crash as soon as I tried to open the Grouping Tool again.



  • So, fresh Poser scene, import blouse obj, create group "Blouse" and add all polys, create group "Buttoned1" and add "Buttoned" material polys.

    In the python shell,
    0_1520263166983_Screen Shot 2018-03-06 at 2.18.52 am.png
    this Weld() method's Doc string implies that it does absolutely no moving of vertices, just alters normals to be parallel for coincident vertices, unlike the Weld Vertices button in the grouping tool, which takes a tolerance input and moves vertices, so calling geom.Weld() should be exactly what is required after AddPolygon() calls.

    Running the following in the Python shell, with just one of the quad polygons, gives:

    >>> meshVerts= oldnumeric.array([
    ... [0.00180099997669 ,0.615831017494 ,0.0114780003205], \
    ... [0.00184200005606 ,0.614763021469 ,0.0115090003237], \
    ... [0.00231699994765 ,0.614197015762 ,0.010827999562], \
    ... [0.00223600002937 ,0.615696012974 ,0.0107859997079]])
    ... 
    >>> p = geom.AddPolygon(meshVerts)
    >>> geom.NumPolygons()
    16705
    >>> p.InGroup('Blouse')
    0
    >>> p.InGroup('Buttoned1')
    0
    >>> p.IncludeInGroup('Buttoned1')
    >>> for mat in geom.Materials():
    ...     pass
    ...     
    >>> for mat in geom.Materials():
    ...     mat.ExtName()
    ...     
    u'Yoke'
    u'Back'
    u'FrontTop'
    u'Shoulders'
    u'Sides'
    u'Front'
    u'CollarInner'
    u'CollarOuter'
    u'Sleeve'
    u'Cuff'
    u'FrontLeftUnder'
    u'FronRightOver'
    u'Buttoned'
    u'Buttons'
    >>> p.SetMaterialName('Buttoned')
    12
    >>> geom.NumVertices()
    16884
    >>> geom.Weld()
    >>> blouse.MarkGeomChanged()
    >>> scene.DrawAll()
    

    Unfortunately, the scene refresh shows the corrupted mesh geometry:
    0_1520264299092_Screen Shot 2018-03-06 at 2.34.11 am.png
    Grrrr!

    Since you have the vertex coordinates you wish to add, the simplest solution I can suggest is to abandon attempting to do any mesh modifications within Poser and just modify the obj file directly.

    However, I have a sneaking suspicion that MarkGeomChanged() is what's broken here.

    I have more testing to do, but I can already exclude the simplest possible path, which is to add all of the existing polygons to NewGeometry and then add the button1 polys. The problem with new geometry is that Poser Python does not implement a method for creating new polygon groups in geometry. You can do it with the Grouping Tool, but you can't drive that from Python, so it's a bust.

    The other possible path I know works is to have a Python script create a new obj file with the added polygons and load that, but you might as well just edit the obj by hand, in that case. Poser has deliberately been prevented from allowing users to easily break EULAs and pass others' object meshes off as their own with minor changes to fool file comparisons, IMVHO.



  • @anomalaus I've seen that happen plenty of times. That's the sign of unassigned vertices in the original mesh. I would take in back into the modeler and delete any double vertices. At least, that was always my problem when I saw that happen.



  • @anomalaus thank you for taking the time to look at this for me, it really is appreciated. and I appologise for the script / obj errors, the code I was using was in my scratch .py file so I had to copy it out and i must have missed the geom assignment.

    I hoped that by doing the add I wouldn't have to produce 32 different variants of the obj to handle the different combinations, but if that is what it takes I'll just have to bite the bullet. I might look at writing a script that modifies the obj (have a master and then edit it and replace whatever the pp2 file points to, that way I can still carry things like morphs and dynamic cloth settings which are of course stored in the prop file.

    It really is beginning to wind me up the apparently random holes in the API, there should have been a directive that everything you can do in the UI you can automate via the API, that is after all what the API is supposed to be for. In fact if I was dev lead I'd insist tht the UI used the API internally so you couldn't miss vital bits like finding what is the current simulation / dynamic group my own bete noire.

    @eclark1849 The mesh is clean, there are no non manifold verts other than edges and certainly no double verts I even checked the buttons didn't accidentally coincide with a vert on the blouse which would not be an issue in the cloth room as the buttons are marked as rigid..



  • @eclark1849 as @amethystpendant mentioned, the mesh is clean. I've just iterated through all the polygon vertex sets and none of the vertices are unused. Something in Poser is definitely broken here. Neither the geom.Weld() nor actor.MarkGeomChanged() methods should cause any movement of vertices. I even tested using either Weld() or MarkGeomChanged() after a single AddPolygon call, and in both cases, the mesh was broken after a scene.DrawAll(). Realignment of normals could cause the appearance of holes in the mesh, if back-facing polygons are hidden, but not misplaced vertices as is evident in the screen grabs I posted.

    @amethystpendant as was posted in another thread, if morphs are evaluated after dynamics, as determined by the parameter evaluation order, they will be included in subsequent dynamics calculations. I would suggest one morph per button which displaces either the button and surrounding mesh inwards, or the hole and surrounding mesh outwards to the point where they disengage from dynamic interaction. That way the user can select exactly which buttons are opened when simulating. Provided those morphs get evaluated after the dynamics.

    Regarding the API holes: from your lips (or fingertips) to SMS' ears (eyes, yes eyes, and give them a good poke). The squeaky wheel gets the grease. The burr under the saddle can't be ignored forever. ;-)



  • @Poser-Team for goodness' sake, we need to be able to create polygon groups in geometries from within Python! It's not good enough that it can be done manually with the Grouping Tool, which cannot itself be manipulated by python scripts. Building a grouped geometry from within Python should always have been possible, and I don't mean use python to write a .obj file and then load that. Come on!


  • Poser Ambassadors

    @anomalaus
    As long as Poser "re-welds vertex groups at import" and "unwelds them at save or export" (effectively doubling all vertex at all welds) thighs like this will continue to happen.

    No python code will overcome this issue.
    I'v been trying for 6 years now for SM to fix this welding-unwelding/vertex doubling at each and every obj file save or export.

    The ONLY cure is a simple one.
    Whenever Poser saves or exports an obj file?
    DELETE it and revert back to the one you build, and properly vertex grouped and welded in your modeler.

    Because : Each time, and there are NO exceptions, each time Poser saves or exports a rigged obj, all vertex at all vertex group welds WILL get a double.

    Put in very simple words.
    There is NO way to rework a rigged obj in Poser without Poser breaking it at each save/export.

    LOL; You can python all your hairs to grey, it's not gonna do it. This bug is in the "core" of the Poser code and goes back some 20+ years or so. NO - LOL.



  • @anomalaus said in More python help needed!:

    @amethystpendant as was posted in another thread, if morphs are evaluated after dynamics, as determined by the parameter evaluation order, they will be included in subsequent dynamics calculations. I would suggest one morph per button which displaces either the button and surrounding mesh inwards, or the hole and surrounding mesh outwards to the point where they disengage from dynamic interaction. That way the user can select exactly which buttons are opened when simulating. Provided those morphs get evaluated after the dynamics.

    I know, but I don't want to have to pre-guess how the two sides will react, I want the simulation to do that under the circumstances of the specific simulation. e.g. I have used a similarly partially buttoned blouse with just the bottom button fastened, but wanted the top open more than would normally happen, so I increased the breast size and moved them outwards very early in the sim, giving the sides a push outwards and a bit of momentum. if I was opening it by a predetermined morph I couldn't do that, same goes for different characters wearing the blouse, it will sim differently depending on things like breast, waist and shoulder size.

    However when I get home I'll have a look at a potential solution using soft dynamics and morphable "button thread" polys. at the moment it is just a supposition so I'll need to test it.

    BTW I released my blouse, did 10 variants but gave instructions on how the user could make different combinations

    So thank you for all your work on this!

    Regarding the API holes: from your lips (or fingertips) to SMS' ears (eyes, yes eyes, and give them a good poke). The squeaky wheel gets the grease. The burr under the saddle can't be ignored forever. ;-)

    @anomalaus said in More python help needed!:

    @Poser-Team for goodness' sake, we need to be able to create polygon groups in geometries from within Python! It's not good enough that it can be done manually with the Grouping Tool, which cannot itself be manipulated by python scripts. Building a grouped geometry from within Python should always have been possible, and I don't mean use python to write a .obj file and then load that. Come on!

    Big +1 from me!

    @vilters This is nothing to do with exporting / importing obj files with groups representing body parts, it is just a plain bog standard obj prop so no rigging, no weld unweld. what @anomalaus was referring to was using the Weld() command from python adding polygons through script, or indeed calling without doing anything.



  • I was getting errors all the time when trying to modify the geometry via API -- only thing apparently 100% safe was to change the XYZ positions of the vertices, but no AddPolygon() from a geometry already in a prop. That was giving me like 100% crashes (note, I was trying to do that on the fly, dynamically).

    The solution I had was to extract the geometry, drop the prop, do the change in the standalone geometry, and then create the prop/actor again from geometry. That behaved well.

    I complained about that in this forum last year. I was told "Oh, you can't do that operation at such-such stage", to what I replied "then the manual needs to clearly state which states you can safely do such-such operations". It's extremely frustrating to have such minimalist reference that just says "Call AddRutabaga() to add a rutabaga!!!!", then you call AddRutabaga() and the thing explodes on you...



  • @fbs7 [<Get Smart's Don Adams voice>]"Ah yes, the old exploding rutabaga trick. Oldest trick in the book." [</Don Adams' voice>]
    Yes, and that route (new grouped geometry from old) is currently impossible without the python API's ability to create polygon groups. As it happened, @amethystpendant 's obj had "g " lines throughout, but Poser ignores unnamed groups completely on import. That OBJ file also has consistent normals defined for every vertex (which is necessary to avoid confusion over back-facing polygons in the turned-over collar).

    @vilters as I mentioned to @amethystpendant , I have python routines which directly create OBJ files and then use Poser's own (buggy, WRT parameter labelling) routines to load them, which I developed while exploring means to directly load DUF props and figures in Poser. I didn't want to suggest that method, as it's a huge kludge which shouldn't be necessary. It is, however, completely effective at creating arbitrary prop geometry within Poser. If the obj loads as a prop, Poser does absolutely nothing to weld or duplicate vertices, only the figure rigging routines do that.

    It seems I will need to make my OBJ geometry load and save scripts public, but I don't want to let SMS off the hook with fixing the gaping holes in their Poser Python API (@Poser-Team ).