Forum Moderators: Staff
Poser Python Scripting F.A.Q (Last Updated: 2024 Sep 18 2:50 am)
The relevant Python operations in this script are as follows.
The idea struck me: hereinunder, am I working on the original values of the vertexes that Poser's renderer works from? Or am I working on a copy and leaving the originals alone?
d=scn.Figure("duck")
unim=d.UnimeshInfo(); dgeom=unim[0]; acts=unim[1]; vinfo=unim[2]
vertices=dgeom.Vertices(); nverts=len(vertices)
polys=dgeom.Polygons(); npolys=len(polys);
vsets=dgeom.Sets(); nvsets=len(vsets);
for i in range(0,npolys):
p=polys[i]
imat=p.MaterialIndex()
nv=p.NumVertices()
st=p.Start()
for j in range(st,st+nv):
k=vsets[j]
v=vertices[k]
x=v.X(); y=v.Y(); z=v.Z()
v.SetY(y+1.0)
P.S. I have tried inserting the line
vertices[k]=v
next after the last line shown above, and calling the script, and still no change shows on rendering.
Should I be working on the separate geometries of each actor of the figure, and not on the geometry of the figure as assembled by calling d.UnimeshInfo()? Or what?
Something appears to not be working any more. Your script looks to be correct. I ran UnimeshDemo.py on the P4 nude male in Poser 2014 and whereas a vertex in his thigh got displaced in previous versions it is no longer apparent now.
I do not know if it is due to various Poser updates or Windows updates but I've found that a number of scripts that worked fine for years now no longer do so.
I have raised this bug at https://mantis.smithmicro.com/view.php?id=39448
I found UnimeshDemo by directory search; it is in Poser11's Runtime/Python/poserScripts/GeomMods
I just now tried UnimeshDemo on my man in boilersuit, and its statement "scene.CreatePropFromGeom(unigeom, "figureProp") " created a prop called figureProp which is a complete duplicate of his geometry, in the default pose with a rotates = 0, and with all the same materials, but the prop's materials are all textured smooth blue and not as in my character.
One vertex in his left thigh was moved.
In my test model, some of the runs of the script print out the vertex coordinates. Some of those printouts show that the vertex values are being changed; but my Poser is ignoring them and working from another copy of the vertexes somewhere in its system, or when displaying or rendering is working straight from the character's geometry file.
I tried UnimeshDemo on the Poser 4 Nude Man, and no vertex was moved either in the man character nor in the prop made from his unimesh geometry.
After that test run, Poser crashed when I tried to delete the Nude Man character, as if the UnimeshDemo had corrupted something in Poser's workings.
I tried UnimeshDemo on the Poser 4 businessman, and a vertex was moved in the man character, but not in the prop made from his unimesh geometry.
After that test run, Poser did not crash when I deleted the character and the prop.
I tried UnimeshDemo on the Poser 4 Nude Man again, and no vertex was moved either in the man character nor in the prop made from his unimesh geometry.
Afterwards, I deleted the character and the prop successfully.
I suspect that somewhere between the Unimesh that Python sees and the displayer / renderer / .OBJ file exporter, the geometry is going through an intermediate buffer, perhaps held in binary form to make it quicker for the displayer / renderer / .OBJ file exporter to read it. And that that buffer is not always being updated often enough from the form that Python sees and works on. If so, Poser needs a function or control to make it flush and update these buffers.
Success at last!
I ran this new script, on my posable duck model, and the jointed parts flew to the side by varying amounts, as expected. The difference is that this time I worked on the .Geometry() of each actor in turn, not on the Unimesh geometry got via unim=d.UnimeshInfo(); dgeom=unim[0]; acts=unim[1]; vinfo=unim[2] . The bug seems to be in the Unimesh system. Is .MarkGeomChanged() intended to work on Unimesh geometry? When did the Unimesh system start to appear in Poser?
import poser
import string
import os
import sys
import aasubrs
scn = poser.Scene()
acs=scn.Actors()
figs=scn.Figures()
d=scn.Figure("duck")
#d=scn.CurrentFigure()
acts=d.Actors()
print "figures:",
for fig in figs:
print fig.Name(),",",
print
print"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
i=0
for a in acts:
i+=1
if a.IsBodyPart():
print "working on",a.Name()
g=a.Geometry()
if g==None: continue
vv=g.Vertices()
nn=0
for v in vv:
x=v.X(); y=v.Y(); z=v.Z()
v.SetX(x+i*.1); nn+=1
a.MarkGeomChanged()
print "worked on",a.Name(),nn,"vertexes"
poser.ProcessCommand(1559)
scn.DrawAll();
Anthony Appleyard posted at 4:35PM Sat, 15 July 2017 - #4309888
Uhh. Thanks. It would be useful if the Poser Python manual said explicitly that UnimeshInfo's output cannot be used to move or create or delete vertexes.
We could derive our own classes to add the behaviour Anthony expacted in the initial post. My question is has someone already done this?
Someone should write a way to write from Unimesh back into the actors' separate geometries.
My script is moving all vertexes which are in a particular volume-range and also in a particular material. Thus I had to look in the polygons, to find which material each was in, and then list all the vertexes of all those polygons. And from that list, to eliminate duplicates, to avoid handling the same vertex more than once. For each polygon vertex, the script must search through that actor's main list of vertexes, and over a big scene that may add up to a long time. In polygon p, it would be useful to have a function p.VertexLink(i), which returns a number k, where the i'th vertex of polygon p is the k'th vertex in the actor's main list of vertexes.Then I can create an index array q, where I can set q[k] = 0 or 1 according to whether vertex k has already been handled. I have experience in such matters: I have written in Visual C++ a mesh-editing program (which I have used to create many of my models), and in it, each corner of each polygon has merely a link pointing to a place in the main list of vertexes.
Is there a way to tell Poser to re-read all geometries from the files?
My test job is duck_at_zero.pz3 . It gets all its geometry from an .obj file. My test script is called quack2.py . I ran duck_at_zero.pz3 and called quack2.py on it, and saved it to duck_at_zero_afterrun_00.pz3. And I found (using a utility called Listitem that I wrote some years ago in Visual C++) that in duck_at_zero_afterrun_00.pz3 , all the actors whose geometry had been changed, now had embedded geometry.
Anthony Appleyard posted at 5:51PM Sun, 16 July 2017 - #4309899
Someone should write a way to write from Unimesh back into the actors' separate geometries.
My script is moving all vertexes which are in a particular volume-range and also in a particular material. Thus I had to look in the polygons, to find which material each was in, and then list all the vertexes of all those polygons. And from that list, to eliminate duplicates, to avoid handling the same vertex more than once. For each polygon vertex, the script must search through that actor's main list of vertexes, and over a big scene that may add up to a long time. In polygon p, it would be useful to have a function p.VertexLink(i), which returns a number k, where the i'th vertex of polygon p is the k'th vertex in the actor's main list of vertexes.Then I can create an index array q, where I can set q[k] = 0 or 1 according to whether vertex k has already been handled. I have experience in such matters: I have written in Visual C++ a mesh-editing program (which I have used to create many of my models), and in it, each corner of each polygon has merely a link pointing to a place in the main list of vertexes.
The following code should build an associative array with the unimesh vert index as the key and returns the actor name(s) and relative vertex number(s). It should then be possible to go through each poly and link back to the actor to change the geom. I don't know if that's necessary as cycling through the actors seems to replace rather than add up changes.
import poser
scn = poser.Scene()
d = scn.CurrentFigure()
unim=d.UnimeshInfo(); dgeom=unim[0]; acts=unim[1]; vinfo=unim[2]
vertices=dgeom.Vertices(); nverts=len(vertices)
polys=dgeom.Polygons(); npolys=len(polys);
vsets=dgeom.Sets(); nvsets=len(vsets);
uniMap={}
actorIndex=0
for actor in acts:
gm = actor.Geometry()
if gm:
vv = gm.Vertices()
vIndx = 0
for v in vv:
uni_index = vinfo[actorIndex][vIndx]
if not (uni_index in uniMap):
uniMap[uni_index] =[(actor.Name(),vIndx)]
else:
uniMap[uni_index].append((actor.Name(),vIndx))
vIndx+=1
actorIndex+=1
print "Test Code - use polyset 5000 on V4"
p=polys[5500]
st=p.Start()
print "Debug Group name ",p.Groups()[0]
print "Debug Materal name ",p.MaterialName()
for j in range(st,st+nv):
k = vsets[j]
if k in uniMap:
print "Unimesh Index ",k
for LocalMap in uniMap[k]:
print "tActor name ",LocalMap[0]
print "tLocal Vertex Index", LocalMap[1]
print "debug name =", uniMap[k][0][0]
dA = d.Actor(uniMap[k][0][0])
dV = dA.Geometry().Vertex(uniMap[k][0][1])
dV.SetX(dV.X()+0.1)
dA.MarkGeomChanged()
Thanks. Currently when I am working with the geometries of the actors:
vv=geom.Vertices(); nv=len(vv)
.............
pp=geom.Polygons()
for p in pp:
if p.MaterialIndex()!=fe: continue
pvv=p.Vertices()
npvv=len(pvv)
for i in range(0,npvv):
v=pvv[i]; k=-1; # Find which main-list vertex is this polygon vertex.
for j in range(0,nv):
if v==vv[j]: k=j; break; # 555
if k<0: print "polygon vertex is not in actor vertexes"; continue
if vc[astart[g]+k]==0: continue # vertex not in range
if vc[astart[g]+k]>1: continue # vertex already attended to
x=v.X(); y=v.Y(); z=v.Z(); v.SetY(y-.01); vc[astart[g]+k]=2 # move the vertex & log it as moved
a.MarkGeomChanged()
This works, but the search at the line with comment "555" is likely to take a long time in a big model, when repeated with every vertex in every polygon in the material "fe" . To make it a bit quicker, I tried this:
for j in range(0,nv):
if pvv[i] is vv[j]: k=j; break; # 555
but it did not work. Poser must know somehow which polygon vertex is which vertex in the actor's main list of vertexes, but how can I quickly access that information?
When I wrote a mesh-editing program in Visual C++, in it a polygon vertex is merely a pointer to a member of the main list of vertexes.
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.
I have written a Python script which looks a figure's Geometry(). OK.
It (in two nested loops) contains this line
x=v.X(); y=v.Y(); z=v.Z()
which looks at the vertex v's coordinates (which are later printed out). OK.
So I changed it to:
which, as obeyed many times in the loop iterations, would have moved a big area of the model's vertexes upwards by about 8 feet 4 inches. But nothing changed on render or when I exported the geometry to an .obj file. Please what must I do to make those changes show on display or render or when I export a geometry .obj file?