I want a generic function that will rotate the uv coordinates of any mesh 90 degrees clockwise or counterclockwise around the positive y axis. How would that be done without using a shader – I only need to do the rotation once at the start of the game.
- Add a script to the object that needs rotated uv
- In the Start function, find the MeshFilter and obtain its mesh
- Get the uv array from mesh.uv
- Rotate every vertex in the array by multiplying it with the Quaternion corresponding to your rotation angle
- Assign the array back to mesh.uv
If this needs to be done for a lot of large meshes, it may be worth putting this functionality in an editor script instead. That may save you some time loading the level with the meshes in it.
Thanks. Two follow up questions:
- Can you provide an example of the quaternion multiplication.
- How do I use editor scripts? Ideally I’d like to make the rotation happen in-editor for certain objects, so as you said, in-game resources aren’t being used.
I meant it quite literally:
Vector3 rotated = Quaternion.Euler(0,0,-90) * Vector3.up;
An AssetPostProcessor is probably the best place for this. Unfortunately, (as far as I know) the only way to communicate with a post processor it is through the file name of the processed asset. So, models that need rotated uv will need a specific string in their name to be able to separate them from other models that don’t need rotated uv:
Hey Sorry to dig ths old thread up but I was trying to do the same thing and I’m really stuck,
Here’s my script :
var DeckMesh : Mesh;
function Update () {
var RotatedUVs : Vector2[] = DeckMesh.uv;//Store the existing UV's
Vector3rotated = Quaternion.Euler(0,0,-90) * Vector3.up;
for (var i = 0 ; i < RotatedUVs.Length; i++){//Go through the array
RotatedUVs[i] += Vector2(.05,.09);//i can move them okay...
print (i);
}
DeckMesh.uv = RotatedUVs;//re-apply the adjusted uvs
}
I can move them okay but I don’t understand how I could get them to rotate?
Thanks
Pete
Try something like this:
var DeckMesh : Mesh;
function Update () {
var RotatedUVs : Vector2[] = DeckMesh.uv;//Store the existing UV's
for (var i = 0 ; i < RotatedUVs.Length; i++){//Go through the array
RotatedUVs[i] += Vector2(.05,.09);//i can move them okay...
var rot = Quaternion.Euler(0,0,-90 * Time.deltaTime);
RotatedUVs[i] = rot * RotatedUVs[i];
}
DeckMesh.uv = RotatedUVs;//re-apply the adjusted uvs
}
This will rotate the uv by 90 degrees every second. I would also highly recommend multiplying your movement vector with Time.deltaTime, as your current animation speed depends on the framerate.
Thanks tomvds, That works! One thing though, it seems to be moving both uv and uv2? Is there a way to isolate them?
It only manipulates uv. To change uv2, you would have to apply the same code to DeckMesh.uv2. Are you sure your shader uses uv2 and not just uv multiple times?
hmm, weird I’ll have to have a look over my shader and see what’s going on there.
Thanks for the help!
I wonder if I could use this for my game.
I’ve big grid mesh for top down 2D game, where each grid square of the mesh is mapped to texture on sprite sheet.
I need to be able to rotate a texture on any given square, would approach posted on this thread work?
For example to set desired texture from sprite sheet I use this code:
int uvIndex = TileIndex * 4;
uvs[uvIndex + 0] = new Vector2(u, v);
uvs[uvIndex + 1] = new Vector2(u+0.0625f, v);
uvs[uvIndex + 2] = new Vector2(u, v+0.0625f);
uvs[uvIndex + 3] = new Vector2(u+0.0625f, v+0.0625f);
So can use same code to rotate texture on part of mesh?
I don’t see any reason why it wouldn’t work. Note that if you need rotations that are not a multiple of 90 degrees, it may look odd as pixels of neighboring sprites from the sprite sheet will fall into your tile.
Thank you. I solved this issue by simply shifting uv’s around, for example to make 90 degree rotation left I set uv1 to uv2, uv2 to uv3, uv3 to uv4 and so on, works perfectly!
Here’s the code I use to rotate a mesh’s UVs around the center point:
public static void RotateUVs(this Vector2[] uvs, float rotationRadians)
{
float rotMatrix00 = Mathf.Cos(rotationRadians);
float rotMatrix01 = -Mathf.Sin(rotationRadians);
float rotMatrix10 = Mathf.Sin(rotationRadians);
float rotMatrix11 = Mathf.Cos(rotationRadians);
Vector2 halfVector = new Vector2(0.5f, 0.5f);
for (int j = 0; j < uvs.Length; j++)
{
// Switch coordinates to be relative to center of the plane
uvs[j] = uvs[j] - halfVector;
// Apply the rotation matrix
float u = rotMatrix00 * uvs[j].x + rotMatrix01 * uvs[j].y;
float v = rotMatrix10 * uvs[j].x + rotMatrix11 * uvs[j].y;
uvs[j].x = u;
uvs[j].y = v;
// Switch back coordinates to be relative to edge
uvs[j] = uvs[j] + halfVector;
}
}