def mapImage(imgMesh, mesh, leftTop, rightBottom): if mh.hasRenderSkin(): try: return mapImageGL(imgMesh.mesh.object3d.textureTex, mesh, leftTop, rightBottom) except Exception as e: log.debug(e) log.debug("Hardware skin rendering failed, falling back to software render.") return mapImageSoft(mh.Image(imgMesh.getTexture()), mesh, leftTop, rightBottom) else: return mapImageSoft(mh.Image(imgMesh.getTexture()), mesh, leftTop, rightBottom)
def mapImage(imgMesh, mesh, leftTop, rightBottom): if mh.hasRenderSkin(): return mapImageGL(imgMesh.mesh.object3d.textureTex, mesh, leftTop, rightBottom) else: return mapImageSoft(mh.Image(imgMesh.getTexture()), mesh, leftTop, rightBottom)
def projectBackground(self): if not self.backgroundChooserView.isBackgroundShowing(): gui3d.app.prompt("Warning", "You need to load a background for the current view before you can project it.", "OK") return mesh = self.human.getSeedMesh() # for all quads, project vertex to screen # if one vertex falls in bg rect, project screen quad into uv quad # warp image region into texture ((x0,y0,z0), (x1,y1,z1)) = self.backgroundImage.mesh.calcBBox() camera = mh.cameras[self.backgroundImage.mesh.cameraMode] x0, y0, _ = camera.convertToScreen(x0, y0, z0, self.backgroundImage.mesh) x1, y1, _ = camera.convertToScreen(x1, y1, z1, self.backgroundImage.mesh) leftTop = (x0, y1) rightBottom = (x1, y0) dstImg = projection.mapImage(self.backgroundImage, mesh, leftTop, rightBottom) texPath = mh.getPath('data/skins/projection.png') if os.path.isfile(texPath): oldImg = mh.Image(texPath) else: oldImg = None gui3d.app.do(ProjectionAction("Change projected background texture", self.human.getTexture(), texPath, oldImg, dstImg)) log.debug("Enabling shadeless rendering on body") self.shadelessButton.setChecked(True) self.human.setShadeless(1) mh.redraw()
def mapMaskSoft(dimensions = (1024, 1024), mesh = None): """ Create a texture mask for the selected human (software renderer). """ progress = Progress() (0) if mesh is None: mesh = G.app.selectedHuman.mesh W = dimensions[0] H = dimensions[1] components = 4 dstImg = mh.Image(width=W, height=H, components=components) dstImg.data[...] = np.tile([0,0,0,255], (H,W)).reshape((H,W,components)) faces = getFaces(mesh) coords = np.asarray([0,H])[None,None,:] + mesh.texco[mesh.fuvs[faces]] * np.asarray([W,-H])[None,None,:] shape = mesh.fvert[faces].shape shape = tuple(list(shape) + [components]) colors = np.repeat(1, np.prod(shape)).reshape(shape) log.debug("mapMask: begin render") progress(0.1, 0.55) RasterizeTriangles(dstImg, coords[:,[0,1,2],:], MaskShader()) progress(0.55, 0.99) RasterizeTriangles(dstImg, coords[:,[2,3,0],:], MaskShader()) log.debug("mapMask: end render") progress.finish() return dstImg
def mapImageSoft(srcImg, mesh, leftTop, rightBottom): progress = Progress() (0) dstImg = mh.Image(G.app.selectedHuman.getTexture()) dstW = dstImg.width dstH = dstImg.height srcImg = srcImg.convert(dstImg.components) camera = getCamera(mesh) faces = getFaces(mesh) # log.debug('matrix: %s', G.app.modelCamera.getConvertToScreenMatrix()) progress(0.05) texco = np.asarray([0,dstH])[None,None,:] + mesh.texco[mesh.fuvs[faces]] * np.asarray([dstW,-dstH])[None,None,:] matrix_ = np.asarray(G.app.modelCamera.getConvertToScreenMatrix(mesh)) coord = np.concatenate((mesh.coord[mesh.fvert[faces]], np.ones((len(faces),4,1))), axis=-1) # log.debug('texco: %s, coord: %s', texco.shape, coord.shape) coord = np.sum(matrix_[None,None,:,:] * coord[:,:,None,:], axis = -1) # log.debug('coord: %s', coord.shape) coord = coord[:,:,:2] / coord[:,:,3:] progress(0.1) # log.debug('coord: %s', coord.shape) # log.debug('coords: %f-%f, %f-%f', # np.amin(coord[...,0]), np.amax(coord[...,0]), # np.amin(coord[...,1]), np.amax(coord[...,1])) # log.debug('rect: %s %s', leftTop, rightBottom) coord -= np.asarray([leftTop[0], leftTop[1]])[None,None,:] coord /= np.asarray([rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]])[None,None,:] alpha = np.sum(mesh.vnorm[mesh.fvert[faces]] * camera[None,None,:], axis=-1) alpha = np.maximum(0, alpha) # alpha[...] = 1 # debug # log.debug('alpha: %s', alpha.shape) # log.debug('coords: %f-%f, %f-%f', # np.amin(coord[...,0]), np.amax(coord[...,0]), # np.amin(coord[...,1]), np.amax(coord[...,1])) progress(0.15) uva = np.concatenate((coord, alpha[...,None]), axis=-1) # log.debug('uva: %s', uva.shape) valid = np.any(alpha >= 0, axis=1) # log.debug('valid: %s', valid.shape) texco = texco[valid,:,:] uva = uva[valid,:,:] # log.debug('%s %s', texco.shape, uva.shape) # log.debug('src: %s, dst: %s', srcImg.data.shape, dstImg.data.shape) log.debug("mapImage: begin render") progress(0.2, 0.6) RasterizeTriangles(dstImg, texco[:,[0,1,2],:], UvAlphaShader(dstImg, srcImg, uva[:,[0,1,2],:])) progress(0.6, 0.99) RasterizeTriangles(dstImg, texco[:,[2,3,0],:], UvAlphaShader(dstImg, srcImg, uva[:,[2,3,0],:])) progress.finish() log.debug("mapImage: end render") return dstImg
def mapUVSoft(mesh=None): """ Project the UV map topology of the selected human mesh onto a texture (software rasterizer). """ progress = Progress()(0) if mesh is None: mesh = G.app.selectedHuman.mesh W = 2048 H = 2048 dstImg = mh.Image(width=W, height=H, components=3) dstImg.data[...] = 0 faces = getFaces(mesh) log.debug("mapUV: begin setup") fuvs = mesh.fuvs[faces] del faces edges = np.array([fuvs, np.roll(fuvs, 1, axis=-1)]).transpose([1, 2, 0]).reshape( (-1, 2)) del fuvs edges = np.where((edges[:, 0] < edges[:, 1])[:, None], edges, edges[:, ::-1]) ec = edges[:, 0] + (edges[:, 1] << 16) del edges ec = np.unique(ec) edges = np.array([ec & 0xFFFF, ec >> 16]).transpose() del ec edges = mesh.texco[edges] * (W, H) progress(0.05) delta = edges[:, 1, :] - edges[:, 0, :] vertical = np.abs(delta[:, 1]) > np.abs(delta[:, 0]) horizontal = -vertical hdelta = delta[horizontal] vdelta = delta[vertical] del delta hedges = edges[horizontal] vedges = edges[vertical] del edges, horizontal, vertical log.debug("mapUV: begin render") progress(0.1, 0.55, "Projecting UV map") rasterizeHLines(dstImg, hedges, hdelta) progress(0.55, 0.99, "Projecting UV map") rasterizeVLines(dstImg, vedges, vdelta) progress(1) log.debug("mapUV: end render") return dstImg.convert(3)
def mapLightingSoft(progressCallback=None): """ Create a lightmap for the selected human. """ mesh = gui3d.app.selectedHuman.mesh W = 1024 H = 1024 dstImg = mh.Image(width=W, height=H, components=4) dstImg._data[...] = 0 delta = (-10.99, 20.0, 20.0) - mesh.coord ld = vnorm(delta) del delta s = np.sum(ld * mesh.vnorm, axis=-1) del ld s = np.maximum(0, np.minimum(255, (s * 256))).astype(np.uint8) mesh.color[..., :3] = s[..., None] mesh.color[..., 3] = 255 del s faces = getFaces(mesh) coords = np.asarray( [0, H])[None, None, :] + mesh.texco[mesh.fuvs[faces]] * np.asarray( [W, -H])[None, None, :] colors = mesh.color[mesh.fvert[faces]] # log.debug("mapLighting: %s %s %s", faces.shape, coords.shape, colors.shape) log.debug("mapLighting: begin render") def progress(base, i, n): if progressCallback == None: gui3d.app.progress(base + 0.5 * i / n, "Projecting lightmap") else: progressCallback(base + 0.5 * i / n) RasterizeTriangles(dstImg, coords[:, [0, 1, 2], :], ColorShader(colors[:, [0, 1, 2], :]), progress=lambda i, n: progress(0.0, i, n)) RasterizeTriangles(dstImg, coords[:, [2, 3, 0], :], ColorShader(colors[:, [2, 3, 0], :]), progress=lambda i, n: progress(0.5, i, n)) gui3d.app.progress(1.0) fixSeams(dstImg) log.debug("mapLighting: end render") mesh.setColor([255, 255, 255, 255]) return dstImg
def combine(image, mhstx): f = open(mhstx, 'rU') try: subTextures = mh.parseINI(f.read(), [("(", "["), (")", "]")]) except: log.warning("subtextures.combine(%s)", mhstx, exc_info=True) f.close() return mh.Image() f.close() texdir = os.path.dirname(mhstx) img = mh.Image(data=image.data) for subTexture in subTextures: path = os.path.join(texdir, subTexture['txt']) subImg = mh.Image(path) x, y = subTexture['dst'] img.blit(subImg, x, y) return img
def mapLightingSoft( lightpos=(-10.99, 20.0, 20.0), mesh=None, res=(1024, 1024), border=1): """ Create a lightmap for the selected human (software renderer). """ progress = Progress()(0) if mesh is None: mesh = G.app.selectedHuman.mesh W = res[0] H = res[1] dstImg = mh.Image(width=W, height=H, components=4) dstImg.data[...] = 0 delta = lightpos - mesh.coord ld = vnormalize(delta) del delta s = np.sum(ld * mesh.vnorm, axis=-1) del ld s = np.maximum(0, np.minimum(255, (s * 256))).astype(np.uint8) mesh.color[..., :3] = s[..., None] mesh.color[..., 3] = 255 del s faces = getFaces(mesh) coords = np.asarray( [0, H])[None, None, :] + mesh.texco[mesh.fuvs[faces]] * np.asarray( [W, -H])[None, None, :] colors = mesh.color[mesh.fvert[faces]] # log.debug("mapLighting: %s %s %s", faces.shape, coords.shape, colors.shape) log.debug("mapLighting: begin render") progress(0.1, 0.5) RasterizeTriangles(dstImg, coords[:, [0, 1, 2], :], ColorShader(colors[:, [0, 1, 2], :])) progress(0.5, 0.9) RasterizeTriangles(dstImg, coords[:, [2, 3, 0], :], ColorShader(colors[:, [2, 3, 0], :])) progress(0.9, 0.99) dstImg = fixSeams(dstImg, mesh, border) log.debug("mapLighting: end render") mesh.setColor([255, 255, 255, 255]) progress.finish() return dstImg
def setEyes(self, human, mhstx): # TODO this will change, for now eyes might only be compatible with the original skin f = open(mhstx, 'rU') try: subTextures = mh.parseINI(f.read(), [("(", "["), (")", "]")]) except: log.warning("setEyes(%s)", mhstx, exc_info=True) f.close() return f.close() texture = mh.getTexture(human.getTexture()) img = mh.Image(human.getTexture()) for subTexture in subTextures: path = os.path.join('data/eyes', subTexture['txt']) subImg = mh.Image(path) x, y = subTexture['dst'] img.blit(subImg, x, y) texture.loadSubImage(img, 0, 0) self.eyeTexture = mhstx
def projectUV(self): dstImg = projection.mapUV() #dstImg.resize(128, 128) texPath = mh.getPath('data/skins/uvtopo.png') if os.path.isfile(texPath): oldImg = mh.Image(texPath) else: oldImg = None gui3d.app.do( ProjectionAction("Change projected UV map texture", self.human.getTexture(), texPath, oldImg, dstImg)) log.debug("Enabling shadeless rendering on body") self.shadelessButton.setChecked(True) self.human.setShadeless(1) mh.redraw()
def projectLighting(self): dstImg = projection.mapLighting() #dstImg.resize(128, 128) texPath = os.path.join(mh.getPath(''), 'data', 'skins', 'lighting.png') if os.path.isfile(texPath): oldImg = mh.Image(texPath) else: oldImg = None gui3d.app.do( ProjectionAction("Change projected lighting texture", gui3d.app.selectedHuman.getTexture(), texPath, oldImg, dstImg)) log.debug("Enabling shadeless rendering on body") self.shadelessButton.setChecked(True) gui3d.app.selectedHuman.mesh.setShadeless(1)
def getTexturePath(self, filePath, fromDir, isTexture, human): srcDir = os.path.realpath(os.path.expanduser(fromDir)) filename = os.path.basename(filePath) if human and (filename == "texture.png"): fromPath = human.getTexture() fileDir = os.path.dirname(fromPath) filename = os.path.basename(fromPath) #print(filePath, fromDir, fileDir, fromPath) if fileDir == fromDir: fromPath = os.path.join(srcDir, filename) else: fromPath = os.path.join(srcDir, filename) if self.useTexFolder: if isTexture: toPath = os.path.join(self.texFolder, filename) else: toPath = os.path.join(self.outFolder, filename) try: self.copiedFiles[fromPath] done = True except: done = False if not done: if 0 and human: img = mh.Image(human.getTexture()) log.debug("%s", dir(img)) img.save(toPath) halt try: shutil.copyfile(fromPath, toPath) except: pass self.copiedFiles[fromPath] = True texPath = toPath else: texPath = os.path.abspath(fromPath) if not self.useRelPaths: return texPath else: return str( os.path.normpath(os.path.relpath(texPath, self.outFolder)))
def changeBackgroundImage(self, side, texturePath): if not side: return if texturePath: # Determine aspect ratio of texture self.texture.loadImage(mh.Image(texturePath)) aspect = 1.0 * self.texture.width / self.texture.height self.filenames[side] = (texturePath, aspect) else: self.filenames[side] = None #self.transformations[side] = [(0.0, 0.0), 1.0] if side == self.getCurrentSide(): # Reload current texture self.setBackgroundImage(side) self.setBackgroundEnabled(self.isBackgroundSet())
def writeTextures(stuffs, outDir, progressCallback=None): def progress(prog): if progressCallback == None: gui3d.app.progress(prog) else: progressCallback(prog) progress(0) i = 0.0 stuffnum = float(len(stuffs)) for stuff in stuffs: if stuff.textureImage: teximg = stuff.textureImage elif stuff.texture: teximg = mh.Image(path=collect.getpath(stuff.texture)) # Export diffuse texture, with subtextures. teximg.save(os.path.join(outDir, "%s_texture.png" % stuff.name)) progress((i + 0.4) / stuffnum) # Export transparency map. imgop.getAlpha(teximg).save( path=os.path.join(outDir, "%s_alpha.png" % stuff.name)) progress((i + 0.8) / stuffnum) # Export bump map. if stuff.bump: collect.copy( stuff.bump, os.path.join( outDir, "%s_bump.%s" % (stuff.name, (stuff.bump[1].split("."))[1]))) elif stuff.displacement: collect.copy( stuff.displacement, os.path.join( outDir, "%s_bump.%s" % (stuff.name, (stuff.displacement[1].split("."))[1]))) i += 1.0 progress(i / stuffnum)
def getOutFileName(filePath, fromDir, isTexture, human, config): srcDir = os.path.realpath(os.path.expanduser(fromDir)) filename = os.path.basename(filePath) if human and (filename == "texture.png"): fromPath = human.getTexture() fileDir = os.path.dirname(fromPath) filename = os.path.basename(fromPath) #print(filePath, fromDir, fileDir, fromPath) if fileDir == fromDir: fromPath = os.path.join(srcDir, filename) else: fromPath = os.path.join(srcDir, filename) if config.separatefolder: if isTexture: toPath = os.path.join(config.texFolder, filename) else: toPath = os.path.join(config.outFolder, filename) try: config.copiedFiles[fromPath] done = True except: done = False if not done: if 0 and human: img = mh.Image(human.getTexture()) log.debug("%s", dir(img)) img.save(toPath) halt try: shutil.copyfile(fromPath, toPath) except: pass config.copiedFiles[fromPath] = True return toPath else: return fromPath
def mapSceneLighting(scn, progressCallback=None): """ Create a lightmap for a scene with one or multiple lights. """ def progress(prog): if (progressCallback is not None): progressCallback(prog) else: pass lnum = float(len(scn.lights)) if (lnum > 0): # Add up all the lightmaps. lmap = mapLighting(scn.lights[0].position, lambda p: progress(p / lnum)) i = 1.0 for light in scn.lights[1:]: lmap = image_operations.mix( lmap, mapLighting(light.position, lambda p: progress( (i + p) / lnum)), 1, 1) i += 1.0 return image_operations.clipped(lmap) else: # If the scene has no lights, return an empty lightmap. return mh.Image(data=np.zeros((1024, 1024, 1), dtype=np.uint8))
def mapImage(imgMesh, mesh, leftTop, rightBottom): if mh.hasRenderSkin(): try: return mapImageGL(imgMesh.mesh.object3d.textureTex, mesh, leftTop, rightBottom) except Exception, e: log.debug(e) log.debug( "Hardware skin rendering failed, falling back to software render." ) return mapImageSoft(mh.Image(imgMesh.getTexture()), mesh, leftTop, rightBottom) else: return mapImageSoft(mh.Image(imgMesh.getTexture()), mesh, leftTop, rightBottom) '''fixSeams A function for removing UV seams from projected images. When creating images through projection, interference with the limits of the UV map tend to produce dark seams on the mesh along the lines that define the limits. Using this procedure, one can repair these seams by UV mask aided post-processing. Pass the image to be fixed in the 'img' parameter, and the mesh from which the UV mask will be projected in the 'mesh' parameter. If you already have a mask projected, you can pass it in place
def setEyes(self, human, mhstx): # TODO this will change, for now eyes might only be compatible with the original skin texture = mh.getTexture(human.getTexture()) texture.loadSubImage( subtextures.combine(mh.Image(human.getTexture()),mhstx), 0, 0) self.eyeTexture = mhstx
def mapUVSoft(): """ Project the UV map topology of the selected human mesh onto a texture. """ mesh = gui3d.app.selectedHuman.mesh W = 2048 H = 2048 dstImg = mh.Image(width=W, height=H, components=3) dstImg._data[...] = 0 faces = getFaces(mesh) log.debug("mapUV: begin setup") fuvs = mesh.fuvs[faces] del faces edges = np.array([fuvs, np.roll(fuvs, 1, axis=-1)]).transpose([1, 2, 0]).reshape( (-1, 2)) del fuvs edges = np.where((edges[:, 0] < edges[:, 1])[:, None], edges, edges[:, ::-1]) ec = edges[:, 0] + (edges[:, 1] << 16) del edges ec = np.unique(ec) edges = np.array([ec & 0xFFFF, ec >> 16]).transpose() del ec edges = mesh.texco[edges] * (W, H) delta = edges[:, 1, :] - edges[:, 0, :] vertical = np.abs(delta[:, 1]) > np.abs(delta[:, 0]) horizontal = -vertical hdelta = delta[horizontal] vdelta = delta[vertical] del delta hedges = edges[horizontal] vedges = edges[vertical] del edges, horizontal, vertical log.debug("mapUV: begin render") def progress(base, i, n): gui3d.app.progress(base + 0.5 * i / n, "Projecting UV map") rasterizeHLines(dstImg, hedges, hdelta, progress=lambda i, n: progress(0.0, i, n)) rasterizeVLines(dstImg, vedges, vdelta, progress=lambda i, n: progress(0.5, i, n)) gui3d.app.progress(1.0) log.debug("mapUV: end render") return dstImg.convert(3)
def setupObjects(name, human, config=None, rigfile=None, rawTargets=[], helpers=False, hidden=False, eyebrows=True, lashes=True, subdivide = False, progressCallback=None): global theStuff, theTextures, theTexFiles, theMaterials def progress(prog): if progressCallback == None: pass else: progressCallback (prog) if not config: config = Config() config.setHuman(human) obj = human.meshData theTextures = {} theTexFiles = {} theMaterials = {} stuffs = [] stuff = CStuff(name, obj = human) if rigfile: stuff.boneInfo = getArmatureFromRigFile(rigfile, obj, config.scale) log.message("Using rig file %s" % rigfile) meshInfo = mh2proxy.getMeshInfo(obj, None, config, None, rawTargets, None) if stuff.boneInfo: meshInfo.weights = stuff.boneInfo.weights theStuff = stuff deleteGroups = [] deleteVerts = None # Don't load deleteVerts from proxies directly, we use the facemask set in the gui module3d _,deleteVerts = setupProxies('Clothes', None, obj, stuffs, meshInfo, config, deleteGroups, deleteVerts) _,deleteVerts = setupProxies('Hair', None, obj, stuffs, meshInfo, config, deleteGroups, deleteVerts) foundProxy,deleteVerts = setupProxies('Proxy', name, obj, stuffs, meshInfo, config, deleteGroups, deleteVerts) progress(0.06*(3-2*subdivide)) if not foundProxy: if helpers: # helpers override everything if config.scale == 1.0: stuff.meshInfo = meshInfo else: stuff.meshInfo = meshInfo.fromProxy(config.scale*obj.coord, obj.texco, obj.fvert, obj.fuvs, meshInfo.weights, meshInfo.shapes) else: stuff.meshInfo = filterMesh(meshInfo, config.scale, deleteGroups, deleteVerts, eyebrows, lashes, not hidden) stuffs = [stuff] + stuffs progbase = 0.12*(3-2*subdivide) progress(progbase) # Apply textures, and subdivide, if requested. stuffnum = float(len(stuffs)) i = 0.0 for stuff in stuffs: progress(progbase+(i/stuffnum)*(1-progbase)) texture = stuff.object.mesh.texture stuff.texture = (os.path.dirname(texture), os.path.basename(texture)) if subdivide: subMesh = cks.createSubdivisionObject( stuff.meshInfo.object, lambda p: progress(progbase+((i+p)/stuffnum)*(1-progbase))) stuff.meshInfo.fromObject(subMesh, stuff.meshInfo.weights, rawTargets) i += 1.0 # Apply subtextures. stuffs[0].textureImage = mh.Image(os.path.join(stuffs[0].texture[0], stuffs[0].texture[1])) mhstx = mh.G.app.getCategory('Textures').getTaskByName('Texture').eyeTexture if mhstx: stuffs[0].textureImage = subtextures.combine(stuffs[0].textureImage, mhstx) progress(1) return stuffs