Fri, Apr 26, 8:38 PM CDT

Welcome to the Poser Python Scripting Forum

Forum Moderators: Staff

Poser Python Scripting F.A.Q (Last Updated: 2024 Apr 26 1:10 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: Flipping Normals


redspark ( ) posted Sun, 21 June 2020 at 7:17 PM ยท edited Tue, 09 April 2024 at 1:39 AM

Hi,

Short of exporting and importing geometry, is there any way to flip the normals of a particular Geometry type? Can the direction of the normals be controlled based on how the vertices are specified? Thanks.

J


redspark ( ) posted Sun, 21 June 2020 at 10:38 PM ยท edited Sun, 21 June 2020 at 10:39 PM

It looks like if you reverse the vertex order defined in each set, Poser points the normals in the opposite direction. So I was able to invert a geometry without exporting and importing. ๐Ÿ˜

J


Miss B ( ) posted Sun, 21 June 2020 at 10:51 PM

Oh, that's good to know. However, I'm not sure how you would reverse the vertex order in Poser.

_______________

OK . . . Where's my chocolate?

Butterfly Dezignz


redspark ( ) posted Sun, 21 June 2020 at 11:23 PM

It seems that there are three parts to the Geometry's mesh: Vertices, Polygons and Sets. The Vertices are just the X,Y,Z coordinates of each point in the mesh. Polygons are defined as two numbers: the Set Index and the number of vertices in the polygon. The Set list is a 1 dimensional array of the vertices that make up all polygons. The Polygon Set Index from the polygon definition tells us the first point in the polygon from the set list and the number of vertices from the polygon definition tells us how many more array elements that polygon takes up. I didn't change the order of the lists of the vertices or the polygons. However, I did use the polygon data to reverse the set list.

So if we have polygon A defined as: [8, 4]. That means that Set[8] is the starting point in the polygon and Set[11] is the last point in the polygon. (Set[8], Set[9], Set[10], Set[11]) So then if we swap the values in 11 and 8 and 9 and 10 around, we have reversed the order of the vertices for that polygon. You just have to repeat that for each polygon in the geometry until all of the polygons have been reversed. That seems to do that trick.

I've only tried it on the Sphere prop but it is working so far. ๐Ÿ˜

J


Miss B ( ) posted Mon, 22 June 2020 at 9:53 AM

Interesting, though seems like a lot of tedious work, depending on the size of the object. A nice script to do that would certainly make it easier. ๐Ÿ˜‰

_______________

OK . . . Where's my chocolate?

Butterfly Dezignz


adp001 ( ) posted Mon, 22 June 2020 at 10:38 AM
import numpy as NP

def po_reverse_normals(actor_or_geom):
    if isinstance(actor_or_geom, poser.ActorType):
        geom = actor_or_geom.Geometry()
    elif isinstance(actor_or_geom, poser.GeomType):
        geom = actor_or_geom
    else:
        raise Exception("Parameter must be actor or geometry.")

    verts = NP.array([[v.X(), v.Y(), v.Z()] for v in geom.Vertices()], NP.float)
    tverts = NP.array([[v.U(), v.V()] for v in geom.TexVertices()], NP.float)
    sets = NP.array([s for s in geom.Sets()], NP.int32)
    tsets = NP.array([s for s in geom.TexSets()], NP.int32)
    polygons = NP.array([[p.Start(), p.NumVertices()] for p in geom.Polygons()], NP.int32)
    tpolygons = NP.array([[p.Start(), p.NumTexVertices()] for p in geom.TexPolygons()], NP.int32)

    for p in polygons:
        start, end = p[0], p[0]+p[1]
        s = v[start:end]
        sets[start:end] = NP.flipud(s)

    new_geom = poser.NewGeometry()
    new_geom.AddGeneralMesh(polygons, sets, verts, tpolygons, tsets, tverts)
    if isinstance(actor_or_geom, poser.ActorType):
        actor_or_geom.SetGeometry(new_geom)
        return actor_or_geom
    else:
        return poser.Scene().CreatePropFromGeom(new_geom)


if __name__ == "__main__":
    po_reverse_normals(poser.Scene().CurrentActor())
    poser.Scene().DrawAll()




adp001 ( ) posted Mon, 22 June 2020 at 10:49 AM

This is based on my basic method to manipulate actors/props. Sometimes I use it to exchange UV maps (without the normal-flip part, of corse :) ).

Aa Sidenote: Poser seams tu use float32 internally. But the code is so old, that it just checks for "numpy.float" โ€“ earlier this results in float32, now it comes out as float64. The check is done inside AddGeneralMesh. So, if one is using a float32 numpy array, AddGeneralMesh will throw an error, because it checks for numpy.float (not float32 or float64, just float).




adp001 ( ) posted Mon, 22 June 2020 at 10:54 AM

Replace


    for p in polygons:
        start, end = p[0], p[0]+p[1]
        s = v[start:end]
        sets[start:end] = NP.flipud(s)

with

    for p in polygons:
        start, end = p[0], p[0]+p[1]
        s = sets[start:end]
        sets[start:end] = NP.flipud(s)




adp001 ( ) posted Mon, 22 June 2020 at 10:59 AM ยท edited Mon, 22 June 2020 at 11:00 AM

On the other side: We have direct access to normals:

for n in geom.Normals():
  print n.X(), n.Y(), n.Z()
  n.SetX(...)




VedaDalsette ( ) posted Mon, 22 June 2020 at 11:22 AM ยท edited Mon, 22 June 2020 at 11:24 AM

When an object needs some of its normals reversed, I use the grouping tool to select those polygons and flip them. But that's not scripting, so nevermind. :)



W10,Intel(R) Core(TM) i5-8600K CPU @ 3.60GHz, 32.0 GB RAM, 64-bit, video GeForce GTX 1050 Ti, 4GB.
Old lady hobbyist.
All visual art or fiction is "playing with dolls."


redspark ( ) posted Mon, 22 June 2020 at 11:57 AM

adp001 posted at 1:51PM Mon, 22 June 2020 - #4392725

On the other side: We have direct access to normals:

for n in geom.Normals():
  print n.X(), n.Y(), n.Z()
  n.SetX(...)

Well, that would be a lot easier. Now, how do I figure out how to make the normal point in the opposite direction? Something to do with Slope?

J


FVerbaas ( ) posted Mon, 22 June 2020 at 3:02 PM ยท edited Mon, 22 June 2020 at 3:04 PM
Forum Coordinator

redspark posted at 9:45PM Mon, 22 June 2020 - #4392732

Well, that would be a lot easier.

Do not mix up two things: The order of the vertices determines which side of the facet is considered 'outside' and which side is 'inside'. The normal vectors just gives the direction of the normal to the surface. If you simply invert the normal vectors by multiplying the ter s with -1, you have not changed what is outside and inside. You will probably just get weird shading. You must rebuild the polygon, or the complete geometry, with reversed vertex order.

Setting normal can serve to introduce ripples and dents in the surface, not to change orientation.


redspark ( ) posted Mon, 22 June 2020 at 4:06 PM

Ok. So I did do it correctly the first time. I reordered all of the vertices for each polygon. It seemed to work but I'm new to this and terrible with math. ๐Ÿ˜€


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.