Last active
February 22, 2023 06:54
-
-
Save rondreas/0cf11e0aa42c03de30f165bcd23c7559 to your computer and use it in GitHub Desktop.
Functions for getting and setting texel density in Maya
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Functions for editing the texel density | |
| https://80.lv/articles/textel-density-tutorial/ | |
| """ | |
| import math | |
| import maya.cmds as mc | |
| import pymel.core as pm | |
| # TODO: Handle non uniform texture sizes, ie: 512x1024 etc... | |
| # TODO: Performance, it is currently quite slow, | |
| def get_uv_isles(mesh): | |
| """ Get each uv isle for the given mesh as a list of mesh faces. | |
| :param mesh: the shape we want to get uv isles from. | |
| :type mesh: pymel.core.nodetypes.Mesh | |
| :returns: list of pymel.core.nodetypes.MeshFace lists | |
| """ | |
| result = [] | |
| shell_ids, number_of_shells = mesh.getUvShellsIds() | |
| shells = tuple([] for _ in range(number_of_shells)) | |
| # Store shells as lists of UVs for each isle | |
| for uv, shell in enumerate(shell_ids): | |
| shells[shell].append(uv) | |
| # For each uv shell, convert the UVs to faces, | |
| # and store as final result. | |
| for shell in shells: | |
| # Get the faces as unicode | |
| faces = pm.polyListComponentConversion( | |
| mesh.map[shell], | |
| fromUV=True, | |
| toFace=True | |
| ) | |
| # Append the pymel object list to result. | |
| result.append(pm.ls(faces, flatten=True)) | |
| return result | |
| def get_texel_density(faces, size=1024): | |
| """ For the supplied faces, calculate the texel density value | |
| :param faces: list of faces | |
| :type faces: pymel.core.nodetypes.MeshFace list | |
| :param size: the size in pixels for the texture | |
| :type size: int | |
| :returns: texel density value as px/unit | |
| :rtype: float | |
| """ | |
| ws_area = 0.0 | |
| uv_area = 0.0 | |
| for face in faces: | |
| ws_area += face.getArea(space='world') | |
| uv_area += face.getUVArea() # By default I hope it picks the current uv set | |
| # Get the square root of the area | |
| ws_area = math.sqrt(ws_area) | |
| uv_area = math.sqrt(uv_area) | |
| px_area = uv_area * size | |
| return px_area / ws_area | |
| def get_uv_boundingbox(uvs): | |
| """ Given a set of uvs return the 2d bounding box. | |
| :param uvs: | |
| :returns: boundingbox min max points in uv space. | |
| """ | |
| u_min = float('inf') | |
| u_max = float('-inf') | |
| v_min = float('inf') | |
| v_max = float('-inf') | |
| for uv in uvs: | |
| # Bit odd how only querying one value returns both u and v values, | |
| u, v = pm.polyEditUV(uv, query=True, uValue=True) | |
| if u < u_min: | |
| u_min = u | |
| if v < v_min: | |
| v_min = v | |
| if u > u_max: | |
| u_max = u | |
| if v > v_max: | |
| v_max = v | |
| return ((u_min, v_min), (u_max, v_max)) | |
| def set_texel_density(faces, density, size=1024): | |
| """ | |
| :param faces: list of faces, assumed to be a uv shell | |
| :type faces: pymel.core.nodetypes.MeshFace list | |
| :param density: | |
| :type density: float | |
| :param size: | |
| :type size: int | |
| """ | |
| # Calculate the uv scale required to set the correct texel density | |
| scale = density / get_texel_density(faces, size) | |
| # For given faces, get the uvs | |
| uvs = pm.ls( | |
| pm.polyListComponentConversion(faces, fromFace=True, toUV=True), | |
| flatten=True | |
| ) | |
| # Get the bounding box for the uvs, | |
| uv_min, uv_max = get_uv_boundingbox(uvs) | |
| # Get the center point from where we will scale, min + half(max-min) | |
| pivot = (uv_min[0] + 0.5*(uv_max[0] - uv_min[0]), uv_min[1] + 0.5*(uv_max[1] - uv_min[1])) | |
| pm.polyEditUV(faces, pivotU=pivot[0], pivotV=pivot[1], scaleU=scale, scaleV=scale) | |
| def main(): | |
| pass | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment