Skip to content

Instantly share code, notes, and snippets.

@nh2

nh2/texcoord-mutator.py

Last active Aug 20, 2020
Embed
What would you like to do?
Script to scale texture coordinates
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.plyfile
import argparse
import sys
import numpy as np
from plyfile import PlyData, PlyElement
parser = argparse.ArgumentParser(description='''
Halves texture coordinates of a PLY file along the vertical axis
(Y axis, "V" in "UV-mapping") axis.
Intended to be used when merging 2 mesh textures with
https://github.com/theFroh/imagepacker
(which simply puts them next to each other horizontally),
and if you want to keep the aspect ratio of the content of the texture
file (if not, you can just stretch-scale it).
To bring the texture back to a standard format like 4096x4096, you can
scale it so that the X axis (e.g. with GIMP) has that dimension, and
fill up the Y axis with some color (unused).
Then you can run this script on the corresponding PLY file to ensure that
it uses only the corresponding half of the image.
IMPORTANT:
The Y-axis filling has to be on the TOP of the image, file, and the
textures have to be at the BOTTOM, because texture mapping starts from
the bottom (V=0).
''')
parser.add_argument("--in-ply", dest='in_ply', help="Input PLY file", required=True)
parser.add_argument("--out-ply", dest='out_ply', help="Output PLY file", required=True)
parser.add_argument("--in-width", dest='in_width', help="Input texture width in px", type=int, required=True)
parser.add_argument("--in-height", dest='in_height', help="Input texture height in px", type=int, required=True)
args = parser.parse_args()
aspect_ratio = float(args.in_height) / float(args.in_width)
print(f"Scale factor is {aspect_ratio}")
print("Reading data...")
with open(args.in_ply, 'rb') as f:
p = PlyData.read(f)
# `p` is immutable; make writeable copy of the texcoords.
print("Making texcoords copy...")
texcoords = [np.array(arr) for arr in p['face']['texcoord']]
print("Mutating texcoords...")
for t in texcoords:
t[[1,3,5]] *= aspect_ratio # 3 triangle edges of UV coordinates; we change the Vs
print("Writing file...")
p['face']['texcoord'] = texcoords
p.write(args.out_ply)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment