Last active
August 30, 2018 09:53
-
-
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.
This file contains 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
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