Skip to content

Instantly share code, notes, and snippets.

@pharan
Last active August 30, 2018 09:53
Show Gist options
  • Save pharan/752d53bde0a40249cabbcfe1694bdba7 to your computer and use it in GitHub Desktop.
Save pharan/752d53bde0a40249cabbcfe1694bdba7 to your computer and use it in GitHub Desktop.
How to calculate how much to trim unused space on backing image for a Spine mesh, and output new UVs that map to the trimmed image.
using System;
public static class SpineMeshUVResizeCalculator {
public struct MeshUVData {
public float[] uvs;
public float imageWidth;
public float imageHeight;
public float trimLeft;
public float trimRight;
public float trimTop;
public float trimBottom;
/// <summary>Create a new MeshUVData struct based on the untrimmed backing image and original mesh.</summary>
public MeshUVData (float[] uvs, float originalImageWidth, float originalImageHeight) {
this.uvs = uvs;
this.imageWidth = originalImageWidth;
this.imageHeight = originalImageHeight;
this.trimLeft = 0;
this.trimRight = 0;
this.trimTop = 0;
this.trimBottom = 0;
}
}
/// <param name="input">MeshUVData populated with only the uvs array and the width and height of the original backing image.</param>
/// <returns>MeshUVData populated with the number of pixels to be removed from the top, right, bottom and left of the original image to get a trimmed image, and the UV mapping coordinates of the new mesh.</returns>
public static MeshUVData GetTrimmedMeshUVData (MeshUVData input) {
int vertexCount = input.uvs.Length / 2;
// 1. Find the trim amounts based on the largest and smallest UV coordinate values.
float xMin = float.PositiveInfinity, yMin = float.PositiveInfinity, xMax = float.NegativeInfinity, yMax = float.NegativeInfinity;
for (int i = 0; i < vertexCount; i++) {
float x = input.uvs[i];
float y = input.uvs[i + 1];
xMin = Math.Min(x, xMin);
yMin = Math.Min(y, yMin);
xMax = Math.Max(x, xMax);
yMax = Math.Max(y, yMax);
}
float deltaXmax = 1f - xMax;
float deltaYmax = 1f - yMax;
// 2. Fill in the new image dimensions.
var output = new MeshUVData();
output.trimLeft = xMin * input.imageWidth; // Pixels to remove from the left.
output.trimTop = yMin * input.imageHeight; // Pixels to remove from the top.
output.trimRight = deltaXmax * input.imageWidth; // Pixels to remove from the right.
output.trimBottom = deltaYmax * input.imageHeight; // Pixels to remove from the bottom
// Use whole-number pixels when trimming.
output.trimLeft = Truncate(output.trimLeft);
output.trimRight = Truncate(output.trimRight);
output.trimTop = Truncate(output.trimTop);
output.trimBottom = Truncate(output.trimBottom);
output.imageWidth = input.imageWidth - output.trimLeft - output.trimRight; // New image width
output.imageHeight = input.imageWidth - output.trimTop - output.trimBottom; // New image height
// 3. Fill in the new UV coordinates.
output.uvs = new float[input.uvs.Length];
for (int i = 0; i < vertexCount; i++) {
// Original x and y
float ox = input.uvs[i];
float oy = input.uvs[i + 1];
// x and y as pixel coordinates.
float pixelX = ox * input.imageWidth;
float pixelY = oy * input.imageHeight;
float newPixelX = pixelX - output.trimLeft;
float newPixelY = pixelY - output.trimTop;
// New x and y.
float nx = newPixelX / output.imageWidth;
float ny = newPixelY / output.imageHeight;
output.uvs[i] = nx;
output.uvs[i + 1] = ny;
}
return output;
}
public static float Truncate (float f) {
return (float)Math.Truncate((double)f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment