Dynamic cloth under stress



  • @eclark1849 said in Dynamic cloth under stress:

    @adp Why is the split in the front of the skirt in the Soft Decorated Cloth Group?

    It's not the split itself. It's the border. And the split has a border too (the yellow dots are the selected vertices for the border):
    0_1531923753855_Bildschirmfoto von 2018-07-18 16-19-39.png
    0_1531923820003_Bildschirmfoto von 2018-07-18 16-20-22.png
    (Remember: The border simulates thickness)



  • @eclark1849
    The reason to make the border Soft Decorated: Poser may "unfold" the border if it is a normal dynamic group and the thickness-effect is gone.



  • @adp Okay, so I didn't understand. The hem you created is not an actual hem? Why not just create a real hem?



  • @eclark1849 said in Dynamic cloth under stress:

    @adp Okay, so I didn't understand. The hem you created is not an actual hem? Why not just create a real hem?

    Do you mean closing the mesh with an additional polygonrow?

    If this is what you mean: If it stays open (vertices are not connected), it has the same effect but an additional row of polygons. Problem is, this polygons are very, very tight to the cloth polygon and poser becomes trouble while moving them around (inside pokes through up to exploding vertices).

    On the other side, connecting the additional polygonrow to the existing vertices results in an unusable mesh. Because it is not allowed that 2 polygons share one edge (Poser may read it in, but you get unpredictable results, even while rendering such a mesh).



  • This is how my border looks like in 2D (I call it border, because it is not a hem :)):
    0_1531925246584_Bildschirmfoto von 2018-07-18 16-36-22.png



  • Remember: I defined the other three vertices as a hem-group. Harder, a bit heavier and less stretchy. Both together results in the desired effect.



  • @adp said in Dynamic cloth under stress:

    Remember: I defined the other three vertices as a hem-group. Harder, a bit heavier and less stretchy. Both together results in the desired effect.

    You're saying the Cloth Room won't work on a tube?



  • @eclark1849 said in Dynamic cloth under stress:

    @adp said in Dynamic cloth under stress:

    Remember: I defined the other three vertices as a hem-group. Harder, a bit heavier and less stretchy. Both together results in the desired effect.

    You're saying the Cloth Room won't work on a tube?

    No! That's not what I mean.
    If you make a hem like a tube, you have to add it as a seperate mesh. No sharing vertices with the cloth!
    You cant connect an edge from the cloth-mesh to the tube-mesh.That's not allowed. Above I made a mistake: One edge can connect 2 Polygons, but not more. What you want is connecting an edge with 2 polys from cloth and additionally a poly from the tube.



  • @amethystpendant said in Dynamic cloth under stress:

    @englishbob said in Dynamic cloth under stress:

    @adp said in Dynamic cloth under stress:

    I made a script for my modeler able to output vertices into a file that Poser can read. This is a big plus, because it's practically impossible to select lots of vertices in Poser.
    (More later)

    Interesting. In the past I've defined special material zones to make it easier to select the dynamic zones I wanted, but of course the minumum selection size is then a facet. You can't define a vertex or a line of vertices this way. You're also left with additional materials in your cloth which may not be useful.

    I'll be interested to see how that works.

    The way I would (have) do(ne) this is to have a material group for the edge one facet deep, another after that, either for the hem or just the cloth. Go into grouping and assign the 1 face depth material as soft decorated. Then go to dynamic group and add the adjacent material, that will effectively remove the second layer of verts from the soft decorated group leaving you with just the one row of verts on the edge

    With Poser 11 I can define a Soft Decorated group and another Dynamic Group with the same vertices. I made this with the waistborder from the trousers. And Poser shows me the vertices in both groups.

    I know it was like you say in previous versions.



  • With the present interest in dynamic clothing, and Roxie being used to model, I decided to publish a set of 26 dynamic clothing items for Roxie I had sitting on my drives for a year or more.

    https://www.contentparadise.com/ProductDetails?id=30127

    alt text

    Some of these go back quite a while and do without edge finishing etc. They may however be useful for experimentation etc.
    No warrants. Have fun and use at your leisure.



  • @adp said in Dynamic cloth under stress:

    @amethystpendant said in Dynamic cloth under stress:

    @englishbob said in Dynamic cloth under stress:

    @adp said in Dynamic cloth under stress:

    I made a script for my modeler able to output vertices into a file that Poser can read. This is a big plus, because it's practically impossible to select lots of vertices in Poser.
    (More later)

    Interesting. In the past I've defined special material zones to make it easier to select the dynamic zones I wanted, but of course the minumum selection size is then a facet. You can't define a vertex or a line of vertices this way. You're also left with additional materials in your cloth which may not be useful.

    I'll be interested to see how that works.

    The way I would (have) do(ne) this is to have a material group for the edge one facet deep, another after that, either for the hem or just the cloth. Go into grouping and assign the 1 face depth material as soft decorated. Then go to dynamic group and add the adjacent material, that will effectively remove the second layer of verts from the soft decorated group leaving you with just the one row of verts on the edge

    With Poser 11 I can define a Soft Decorated group and another Dynamic Group with the same vertices. I made this with the waistborder from the trousers. And Poser shows me the vertices in both groups.

    I know it was like you say in previous versions.

    I believe you can have up to three groups (maybe a fourth, if I'm not misunderstanding the manual) in one object.



  • @eclark1849 I'm going to end the conversation on my part so you can do whatever you're doing without my distractions.



  • @englishbob I found the script I talked about (reading vertices from an UV-map).

    Make an image with the UV-map from your clothpiece. Mark the vertexpoints you want red with the brush from your image-editor. Save the image.
    In Poser select the cloth-actor. Run the script. The script will open a file-dialog where you can select your created image. A second later you will find a pz2-file in the folder the image is located, same name, but extension pz2.
    If the script is ready it prints the filename out and loads it. Your clothactor has now a new vertexlist with the name of your image and an appended "_vt".
    The script is fast, so no need to fiddle with the pz2-file.

    You have to make sure the vertexpoints are completly covered in red. Make a few tests to find out what works for you. You can change the values in function "is_red" to define your own "red" color.

    from __future__ import print_function
    import os
    
    try:
        import poser
        SCENE = poser.Scene()
    except ImportError:
        raise Exception("This script needs Poser")
    
    from PIL import Image as IMG
    
    try:
        START_PATH
    except NameError:
        START_PATH = poser.ContentRootLocation()
    
    PZ2_HEADER = """{
        version 
            {
                number 9
            }
    
    """
    
    ##############################################################################
    # called for every defined tex-vertex to check the color.
    def is_red(r, g, b):
        return r > 160 and g < 40 and b < 40
    
    ##############################################################################
    
    def generate_Vertexlist_from_UVmap(imgname, actorname=None, groupname="uv_generated", pz2_file=None):
        actor = image = None
    
        if actorname is None:
            actor = SCENE.CurrentActor()
        elif isinstance(actorname, (str, unicode)):
            actor = SCENE.Actor(actorname)
    
        if not isinstance(actor, poser.ActorType):
            raise ValueError("Actor not found or none given")
    
        # make sure a prop or bodypart of a figure is selected
        if not (actor.IsProp() or actor.IsBodyPart()):
            raise Exception("Select a Prop or Bodypart first!")
    
        geom = actor.Geometry()
        if geom is None:
            raise ValueError("Actor '%s' has no geometry" % actor.Name())
    
        sets = geom.Sets()
    
        # open image
        if not IMG.isImageType(imgname):
            try:
                image = IMG.open(imgname)
            except:
                raise ValueError("Couldn't open image '%s'" % imgname)
    
        image = image.convert("RGB")
        # width and high to compute UV-coordinates
        w, h = image.size[0] - 1, image.size[1] - 1
    
        seen = set() # already seen vertices
        ar = list()  # list of vertex indices
    
        for tp in geom.TexPolygons():
            idx = tp.Start()
            for iv, tv in enumerate(tp.TexVertices()):
                ux, uy = tv.U(), tv.V()
                set_idx = sets[idx + iv]
                if not set_idx in seen:
                    seen.add(set_idx)
                    x = round(w * ux, 0) % w
                    y = (h - round(h * uy, 0)) % h
                    c = image.getpixel((x, y))
                    if is_red(*c):
                        ar.append(set_idx)
    
        if pz2_file is None:
            pz2_file = imgname.rsplit(".")[0]+".pz2"
    
        if groupname is not None:
            groupname = os.path.basename(imgname).rsplit(".")[0]+"_vt"
    
        try:
            fh = open(pz2_file, "w")
        except Exception as err:
            print("can't open weightmapfile '%s'" % pz2_file)
        else:
            print(PZ2_HEADER, file=fh)
            tab = lambda n: "\t" * n
            t = 1
            print("%sactor %s" % (tab(t), actor.InternalName()), file=fh)
            t += 1
            print("%s{" % tab(t), file=fh)
            print("%svertsGroup %s" % (tab(t), groupname), file=fh)
            t += 1
            for vidx in sorted(ar):
                print("%s%s" % (tab(t), vidx), file=fh)
    
            t -= 1
            print("%s}" % tab(t), file=fh)
            t -= 1
            print("%s}" % tab(t), file=fh)
            t -= 1
            print("%s}" % tab(t), file=fh)
    
            fh.close()
    
            return pz2_file
    
    
    ##############################################################################
    
    if __name__ == "__main__":
        dialog = poser.DialogFileChooser(poser.kDialogFileChooserOpen,
                                             None,
                                             "Select an UV-mapped Image",
                                             START_PATH)
        if dialog.Show():
            if os.path.isfile(dialog.Path()):
                START_PATH = os.path.dirname(dialog.Path())
                pz2_file = generate_Vertexlist_from_UVmap(imgname=dialog.Path())
                SCENE.LoadLibraryPose(pz2_file)
                SCENE.DrawAll()
                print("PZ2-file created:", pz2_file)
            else:
                print("Not an usable file:", dialog.Path())
    


  • @adp said in Dynamic cloth under stress:

    @englishbob I found the script I talked about (reading vertices from an UV-map).

    Make an image with the UV-map from your clothpiece. Mark the vertexpoints you want red with the brush from your image-editor. Save the image.
    In Poser select the cloth-actor. Run the script. The script will open a file-dialog where you can select your created image. A second later you will find a pz2-file in the folder the image is located, same name, but extension pz2.
    If the script is ready it prints the filename out and loads it. Your clothactor has now a new vertexlist with the name of your image and an appended "_vt".
    The script is fast, so no need to fiddle with the pz2-file.

    You have to make sure the vertexpoints are completly covered in red. Make a few tests to find out what works for you. You can change the values in function "is_red" to define your own "red" color.

    from __future__ import print_function
    import os
    
    try:
        import poser
        SCENE = poser.Scene()
    except ImportError:
        raise Exception("This script needs Poser")
    
    from PIL import Image as IMG
    
    try:
        START_PATH
    except NameError:
        START_PATH = poser.ContentRootLocation()
    
    PZ2_HEADER = """{
        version 
            {
                number 9
            }
    
    """
    
    ##############################################################################
    # called for every defined tex-vertex to check the color.
    def is_red(r, g, b):
        return r > 160 and g < 40 and b < 40
    
    ##############################################################################
    
    def generate_Vertexlist_from_UVmap(imgname, actorname=None, groupname="uv_generated", pz2_file=None):
        actor = image = None
    
        if actorname is None:
            actor = SCENE.CurrentActor()
        elif isinstance(actorname, (str, unicode)):
            actor = SCENE.Actor(actorname)
    
        if not isinstance(actor, poser.ActorType):
            raise ValueError("Actor not found or none given")
    
        # make sure a prop or bodypart of a figure is selected
        if not (actor.IsProp() or actor.IsBodyPart()):
            raise Exception("Select a Prop or Bodypart first!")
    
        geom = actor.Geometry()
        if geom is None:
            raise ValueError("Actor '%s' has no geometry" % actor.Name())
    
        sets = geom.Sets()
    
        # open image
        if not IMG.isImageType(imgname):
            try:
                image = IMG.open(imgname)
            except:
                raise ValueError("Couldn't open image '%s'" % imgname)
    
        image = image.convert("RGB")
        # width and high to compute UV-coordinates
        w, h = image.size[0] - 1, image.size[1] - 1
    
        seen = set() # already seen vertices
        ar = list()  # list of vertex indices
    
        for tp in geom.TexPolygons():
            idx = tp.Start()
            for iv, tv in enumerate(tp.TexVertices()):
                ux, uy = tv.U(), tv.V()
                set_idx = sets[idx + iv]
                if not set_idx in seen:
                    seen.add(set_idx)
                    x = round(w * ux, 0) % w
                    y = (h - round(h * uy, 0)) % h
                    c = image.getpixel((x, y))
                    if is_red(*c):
                        ar.append(set_idx)
    
        if pz2_file is None:
            pz2_file = imgname.rsplit(".")[0]+".pz2"
    
        if groupname is not None:
            groupname = os.path.basename(imgname).rsplit(".")[0]+"_vt"
    
        try:
            fh = open(pz2_file, "w")
        except Exception as err:
            print("can't open weightmapfile '%s'" % pz2_file)
        else:
            print(PZ2_HEADER, file=fh)
            tab = lambda n: "\t" * n
            t = 1
            print("%sactor %s" % (tab(t), actor.InternalName()), file=fh)
            t += 1
            print("%s{" % tab(t), file=fh)
            print("%svertsGroup %s" % (tab(t), groupname), file=fh)
            t += 1
            for vidx in sorted(ar):
                print("%s%s" % (tab(t), vidx), file=fh)
    
            t -= 1
            print("%s}" % tab(t), file=fh)
            t -= 1
            print("%s}" % tab(t), file=fh)
            t -= 1
            print("%s}" % tab(t), file=fh)
    
            fh.close()
    
            return pz2_file
    
    
    ##############################################################################
    
    if __name__ == "__main__":
        dialog = poser.DialogFileChooser(poser.kDialogFileChooserOpen,
                                             None,
                                             "Select an UV-mapped Image",
                                             START_PATH)
        if dialog.Show():
            if os.path.isfile(dialog.Path()):
                START_PATH = os.path.dirname(dialog.Path())
                pz2_file = generate_Vertexlist_from_UVmap(imgname=dialog.Path())
                SCENE.LoadLibraryPose(pz2_file)
                SCENE.DrawAll()
                print("PZ2-file created:", pz2_file)
            else:
                print("Not an usable file:", dialog.Path())
    

    So .. it reads an image file and makes that into a PZ2??? O.o Wow. I didn't know that was possible. Awesome :D



  • @trekkiegrrrl said in Dynamic cloth under stress:

    So .. it reads an image file and makes that into a PZ2??? O.o Wow. I didn't know that was possible. Awesome :D

    Not like it sounds. Just the vertex-part is written. But that is enough to get the vertex-group defined.



  • @adp said in Dynamic cloth under stress:

    @trekkiegrrrl said in Dynamic cloth under stress:

    So .. it reads an image file and makes that into a PZ2??? O.o Wow. I didn't know that was possible. Awesome :D

    Not like it sounds. Just the vertex-part is written. But that is enough to get the vertex-group defined.

    Sounds intriguing. I will definitely have to try this one out :)



  • @adp
    Thank you for this!!!
    It comes in extemely handy for a project I am exploring.



  • @adp this is really great stuff! I think what you meant to say, though, is that "it is not allowed that [more than] 2 polygons share one edge" normal meshes always allow 2 polygons to share an edge, otherwise cloth could only be single facets :-) [Oh, I see you did correct that, subsequently, D'Oh :-)]

    I believe the non-deterministic results in that (3 facets share an edge) case stem from normals being directly tied one-to-one to vertices and internally calculated by Poser from the winding order of the facet edges. As soon as you have three facets, the normals of the shared vertices can be degenerate (zero, or nonsense values) due to the opposing facet normals.

    @eclark1849 a tube will have all of its facets and normals facing inwards or outwards, without contradiction (unless the normals of one facet around the circumference has been flipped, which gives strange render holes. Just see what Poser makes of a properly modeled möbius strip (with thickness - there's one, I think from the late D3D Ralph Sessler bundled with P11, IIRC) in preview; weird!

    @adp this vertex grouping by pose file application is really interesting. I've obviously not played enough with cloth simulations and looked at the files that Poser saves out (the prop files, not the simulations) to see how it's stored the vertexGroups. I wonder if this could be a useful, stop-gap mechanism to create new vertex groups (which the Python API cannot yet create) that can be seen by the Grouping Tool, not just within the Cloth Room? I'd previously tried to do the same thing with HairGroups, but failed in my attempt to have Poser recognise them within a python script.



  • @adp said in Dynamic cloth under stress:

    @englishbob I found the script I talked about (reading vertices from an UV-map).

    @trekkiegrrrl said in Dynamic cloth under stress:

    I didn't know that was possible. Awesome :D

    TG is right, that's far more awesome than I would have thought possible. Thank you!



  • @anomalaus Thanks for the translation :)
    I have a hard time to express myself in english. I'm mutch better with the german language ;)

    this vertex grouping by pose file application is really interesting. I've obviously not played enough with cloth simulations and looked at the files that Poser saves out (the prop files, not the simulations) to see how it's stored the vertexGroups.

    The vertexgroups are only in the prop-file. In plain text as usual. The simuation itself, I asume, is a compressed Alembic-format (open source at git, if you are interested).

    I wonder if this could be a useful, stop-gap mechanism to create new vertex groups (which the Python API cannot yet create) that can be seen by the Grouping Tool, not just within the Cloth Room? I'd previously tried to do the same thing with HairGroups, but failed in my attempt to have Poser recognise them within a python script.

    I think this is not possible. Poser defines meshes as a whole. A mesh stored in a Poser file is nothing more as a plain OBJ file as you may know.

    I didn't try with hair (never used it in all those years). But I think at least creating hair groups should be possible. Because morphs, parameters, actor definitions, even parameters for joints can be redefined with poser-file fragments (cr2, pz2, etc).

    I use this method very often to load weightmaps into figures/props created in C4D (now Poser-Python can read/write weightmaps directly; but not weightmaps stored as UV-Images ;) ).

    Another thing one can make with UV-maps is creating morph. May come in handy if one has to move some vertices you simply cant reach from within Poser.