import poser import Numeric,os,gzip import tkMessageBox scene = poser.Scene() def run(actS,actT,dataPath): if os.path.exists(dataPath): windex,weights = read_file(dataPath,actT.Geometry().NumVertices(),actS.Geometry().NumVertices()) if windex == None: readerror("Datafile for selected actors was not found." "Meshes must be analysed before morphs can be copied.\n") return else: readerror("No data file found" "Meshes must be analysed before morphs can be copied.\n") return meshS = myMesh(actS.Geometry(),actS) meshT = myMesh(actT.Geometry(),actT) meshS.init_UV() meshT.init_UV() tverts = transfer_UVs(meshS,meshT,windex,weights) map_object(actT.Geometry(),tverts,replace=0) def transfer_UVs(mS,mT,windex,weights): """ Transfer the UVs from the source to the target Does not currently handle seams (vertices with multiple corresponding texvertices) in either the source or the target. """ srcUVs = mS.uvs points = [i for i in mT.uvs] for vi in range(mT.geom.NumVertices()): # Target verts if windex[vi]: for uvi in mT.vuv[vi]: # Loop through texverts for target vert point = [0.0,0.0] for w in range(len(windex[vi])): #Get corresponding source texverts win = windex[vi][w] way = weights[vi][w] for t in range(len(mS.vuv[win])): #There may be more than 1 texvert per source vert tuvs = mS.vuv[win][t] tu = srcUVs[tuvs][0]*way tv = srcUVs[tuvs][1]*way point = [point[0]+tu,point[1]+tv] points[uvi] = [point[0],point[1]] return points class myMesh(object): def __init__(self,geom,act): self.act = act self.geom = geom self.verts = vertexPos(self.geom) def init_UV(self): self.polyverts(self.geom,self.geom.Polygons()) self.polyverts(self.geom,self.geom.TexPolygons(),UV=1) self.vertuvs(self.geom,self.pverts,self.puv) #self.texverts = [i for i in self.geom.TexVertices()] # This is silly, but it speeds up all the texvert lookups immensely. self.UVs() def polyverts(self,geom,polys,UV=0): """ vertices by polygon - this is the Sets() list broken down by polygon index. Returns a list of Numeric arrays """ if UV: self.puv = [] gset = geom.TexSets() else: self.pverts = [] gset = geom.Sets() for p in polys: if UV: l = p.NumTexVertices() else: l = p.NumVertices() s = p.Start() e = s + l vl = Numeric.array([v for v in gset[s:e]],Numeric.Int) if UV: self.puv.append(vl) else: self.pverts.append(vl) def vertuvs(self,geom,pgons,uvgons): """ Returns a Numeric array of vert indices to texvert indices for the geom pgons is pverts or tverts uvgons is puv or tuv Do not mix use of tris and polys! """ self.vuv = [[] for i in range(geom.NumVertices())] screen = [[] for i in range(geom.NumVertices())] for i in range(len(pgons)): for j in range(len(pgons[i])): if not uvgons[i][j] in screen[pgons[i][j]]: self.vuv[pgons[i][j]].append(uvgons[i][j]) screen[pgons[i][j]].append(uvgons[i][j]) def UVs(self): """ Organize the UV data into a Numeric array """ geom = self.geom uvverts = [i for i in geom.TexVertices()] self.uvs = [[] for i in range(geom.NumTexVertices())] for i in range(len(uvverts)): tv = uvverts[i] self.uvs[i] = [tv.U(),tv.V()] self.uvs = Numeric.array(self.uvs,Numeric.Float) uvverts = [] def readerror(message): #app.status_update(message) err = tkMessageBox.showinfo("Error reading datafile",message) #=============================================================================================== # File-reading and morph creation (adapted from TDMT Classic with minimal necessary changes) - Original function by Spanki #=============================================================================================== def read_file(path,numverts,srcverts): if not os.path.exists(path): return None, None indices = [[] for i in range(numverts)] weights = [[] for i in range(numverts)] ext = os.path.splitext(path)[1] if ext == ".vmf": thefile = open(path,"r") else: thefile = gzip.GzipFile(path) if thefile: lines = thefile.readlines() thefile.close() header_found = 0 for line in lines: c = line.replace('\n','').split(None) # Split line on white-space #----- First check for blank and/or comment lines if len(c) == 0 or c[0][0] == '#': continue #----- Check for header record if c[0] == 'TDMT_Matched': header_found = 1 if len(c) > 1: version = c[1] # If the script relies on some specific format of the file, it can do that test here if len(c) > 2: sv_count = int(c[2]) if len(c) > 3: dv_count = int(c[3]) if sv_count != srcverts or dv_count != numverts: readerror("Incompatible vertex counts!") return None,None # Maybe insert code to display ok/cancel dialog if vert counts don't match #----- Check for description/comment records elif c[0] == 'comment:': if header_found == 0: readerror("Error reading comment in\n%s" %(line)) return None,None if len(c) > 1: uc = line.split(': ') user_comment = uc[1] #----- Check for actors record elif c[0] == 'actors:': if header_found == 0: readerror("Error reading actors in\n%s" %(line)) return None,None if len(c) > 1: source_actor = c[1] if len(c) > 2: target_actor = c[2] # Do whatever is needed with actor names here (or store for later) elif c[0] == "w": # This section has been altered to allow reading of .vmf files vi = int(c[1]) numweights = int(c[2]) for i in range(numweights): indices[vi].append(int(c[i+3])) if c[0] == "w": for i in range(numweights): weights[vi].append(float(c[i+numweights+3])) return indices, weights else: return None, None def map_object(geom,tverts,replace=0): """ Apply new UV mapping to the specified actor and create a new prop with the altered geometry. If replace == 1, selected actor will have geometry replaced instead of creating a new prop. """ sets = [i for i in geom.Sets()] polys = [[p.Start(),p.NumVertices()] for p in geom.Polygons()] verts = [[i.X(),i.Y(),i.Z()] for i in geom.Vertices()] sets = Numeric.array(sets,Numeric.Int) polys = Numeric.array(polys,Numeric.Int) verts = Numeric.array(verts,Numeric.Float) #tverts = [[i.U(),i.V()] for i in geom.TexVertices()] tsets = [i for i in geom.TexSets()] tpolys = [[p.Start(),p.NumVertices()] for p in geom.Polygons()] tverts = Numeric.array(tverts,Numeric.Float) tsets = Numeric.array(tsets,Numeric.Int) tpolys = Numeric.array(tpolys,Numeric.Int) newgeom = poser.NewGeometry() newgeom.AddGeneralMesh(polys,sets,verts,tpolys,tsets,tverts) for mat in geom.Materials(): newgeom.AddMaterialName(mat.Name()) correct_indices = 0 if geom.Materials()[0].Name() != "Preview": correct_indices = 1 for pi in range(geom.NumPolygons()): # Need to find matched polys by incenter poly = geom.Polygon(pi) newpoly = newgeom.Polygon(pi) newpoly.SetMaterialIndex(poly.MaterialIndex()+correct_indices) if replace: scene.CurrentActor().SetGeometry(newgeom) scene.CurrentActor().MarkGeomChanged() else: newprop = scene.CreatePropFromGeom(newgeom,"newprop") scene.SelectActor(newprop) scene.DrawAll() # To let the new material names sink in. for mat in geom.Materials(): matname = mat.Name() diffuse = mat.DiffuseColor() newprop.Material(matname).SetDiffuseColor(diffuse[0],diffuse[1],diffuse[2]) newprop.Material(matname).SetTextureMapFileName(mat.TextureMapFileName()) dataPath = "C:\\Program Files\\e frontier\\Poser 7\\Runtime\\Python\\poserScripts\\TDMTfiles\\matched\\blMilWom_v3-Antonia-121\\head-head" dataPath = dataPath.replace("\\",os.sep) dataPath = os.path.normpath(os.path.join(dataPath,"posted.vmz")) actS = scene.Figure("Figure 2").Actor("head") actT = scene.Figure("Antonia-121").Actor("head") run(actS,actT,dataPath)