import poser, math try: import Numeric oldnumeric = Numeric except: import numpy as Numeric #Numeric = numpy Numeric.Int = Numeric.int Numeric.Float = Numeric.float Numeric.matrixmultiply = Numeric.dot import numpy.oldnumeric as oldnumeric FLT_EPSILON = 1.19209290e-07 scene = poser.Scene() def show_weights(act,weights=[],show=1): if not weights: figweights = get_weights_complex(act.ItsFigure()) weights = figweights[str(act.InternalName())] print act.Name() print weights print "************************" verts = vertexPos(act.Geometry()) for vi in range(len(verts)): w = weights[vi] if show: build_box_mats(point=verts[vi],name="weights",merge=1,matname=str(w),color=(1-w,w,0.0)) else: # Reverse red and green, to visualize hypothetical parent influences build_box_mats(point=verts[vi],name="weights",merge=1,matname=str(w),color=(w,1-w,0.0)) def get_weights_complex(fig,axis=-1): """ Poser only gives us the old legacy JointVertexWeights() and TwistVertexWeights() for weight map data about an actor. These are organized by axis of rotation, and any one of them can contain zero weights. Actors may return no weights at all, and any given vertex may have a weight listing of 'None'. To make anything useful of this information, the None and 0.0 weights need to be modified. Here, the Joint and Twist weights for the actor's three axes are averaged, to try to derive a single, comprehensive weight set. """ parentActor = fig.ParentActor() # A figure may be parented to another figure or a prop. Need to isolate BODY. if (not parentActor.IsBodyPart()) or (parentActor.IsBodyPart() and parentActor.ItsFigure().InternalName() != fig.InternalName()): acts = [a for a in fig.Actors() if not a.Geometry() and a.IsBodyPart()] parentActor = acts[0] figweights = {} for act in fig.Actors(): if (not act.IsBodyPart()) or (not act.Geometry()): continue vertrange = range(act.Geometry().NumVertices()) strings = ("x","y","z") actweights = [0.0 for i in vertrange] numweights = [0 for i in vertrange] for axis in strings: weights = act.JointVertexWeights(axis) if weights != None: for vi in vertrange: w = weights[vi] if w != None: actweights[vi] += w numweights[vi] += 1 else: weights = act.TwistVertexWeights(axis) if weights != None: for vi in vertrange: w = weights[vi] if w != None: actweights[vi] += w numweights[vi] += 1 for vi in vertrange: n = numweights[vi] if n: actweights[vi] /= n if actweights == None: actweights == [1.0 for i in act.Geometry().Vertices()] #actweights == [0.0 for i in act.Geometry().Vertices()] if act.Parent().InternalName() == parentActor.InternalName(): #print act.Name(), act.Parent().Name() actweights == [1.0 for i in act.Geometry().Vertices()] for i in range(len(actweights)): if actweights[i] == None: # Should be average of neighbor vertices actweights[i] = 0.0 #else: #actweights[i] = math.ceil(actweights[i]*1000000)/1000000 #if actweights[i] > 0.99: # actweights[i] = 1.0 #if actweights[i] == 0.0: # actweights[i] = 1.0 #if actweights[i] < 0.5: # actweights[i] = 1.0 figweights[str(act.InternalName())] = actweights return figweights def build_box_mats(box=None,point=None,sz=0.00175,name="newbox",display=0,rotmat=None,merge=0,matname='Preview',color=[1,1,1]): """Add a box, with materials""" if (box == None) and (point == None): return if box != None: b1 = box if point != None: b1 = [point[0]-sz, point[0]+sz, point[1]-sz, point[1]+sz, point[2]-sz, point[2]+sz] addmesh = 0 if merge: props = [a for a in scene.Actors() if a.Name() == name and a.IsProp()] if len(props) >= 1: addmesh = 1 if addmesh: prop = props[0] newprop = prop.Geometry() addpolys = newprop.NumPolygons() else: addpolys = 0 newprop = poser.NewGeometry() verts = Numeric.array([ [b1[0],b1[2],b1[4]], [b1[0],b1[3],b1[4]], [b1[0],b1[3],b1[5]], [b1[0],b1[2],b1[5]],[b1[1],b1[2],b1[4]],[b1[1],b1[3],b1[4]], [b1[1],b1[3],b1[5]],[b1[1],b1[2],b1[5]] ], Numeric.Float) polys = Numeric.array([[0,4],[4,4],[8,4],[12,4],[16,4],[20,4]],Numeric.Int) sets = Numeric.array([3,2,1,0,4,5,6,7,5,4,0,1,6,5,1,2,7,6,2,3,4,7,3,0],Numeric.Int) if rotmat: for vi in range(len(verts)): v = verts[vi] v1 = point_by_matrix(v,rotmat) for i in range(3): verts[vi][i] = v1[i] newprop.AddGeneralMesh(polys,sets,verts) if addmesh: prop.SetGeometry(newprop) else: prop = scene.CreatePropFromGeom(newprop,name) newprop = prop.Geometry() # This is necessary to enable Poser 5 and 6 to add new materials to the geom. newprop.AddMaterialName(matname) for pi in range(len(polys)): newpoly = newprop.Polygon(pi+addpolys) newpoly.SetMaterialName(matname) prop.SetGeometry(newprop) material = prop.Material(matname) material.SetDiffuseColor(color[0],color[1],color[2]) material.SetAmbientColor(color[0],color[1],color[2]) if display == 1: prop.SetDisplayStyle(poser.kDisplayCodeEDGESONLY) elif display == 2: prop.SetDisplayStyle(poser.kDisplayCodeWIREFRAME) return prop def vertexPos(geom,worldspace=1,multiple=1.0): """ Pre-fetch vertex coordinates for faster access. Returns a Numeric array of vert coords by vert indices Send worldspace=0 keyword when calling function, to use localspace From TDMT Classic source code. """ numVerts = geom.NumVertices() verts = [[0.0,0.0,0.0] for i in range(numVerts)] for i in range(numVerts): if worldspace: v = geom.WorldVertex(i) else: v = geom.Vertex(i) verts[i] = [v.X(),v.Y(),v.Z()] verts = Numeric.array(verts,Numeric.Float) return verts def get_weldgoals(actor,verts,parent,child): """Gather weld goal information for an actor.""" screen = [[None,0,0] for i in verts] if not actor.IsBodyPart(): return if child: acts = actor.Children() else: acts = [] if parent: acts.append(actor) for act in acts: if act.Name() == actor.Name(): welds = [[j for j in range(len(i)) if i[j] != -1] for i in act.WeldGoals()] else: welds = [[j for j in i if j != -1] for i in act.WeldGoals()] for j in welds: for i in j: if act.Name() == actor.Name(): self.screen[i] = [actor.Parent(),1,1] else: self.screen[i] = [act,1,1] show_weights(scene.CurrentActor())