- Home /
 
 
               Question by 
               stoneblade · Apr 07, 2015 at 01:03 AM · 
                texturerotateimagemath  
              
 
              Rotating texture with 3 shear
I'm trying to implement this,I'm having trouble keeping the image to the center as it rotate around the center
i.e. calculating a correct offset to the shear so the image remain centered
I'm not looking for it to be perfect, but at least -45 and 45 degree having the same image when using a symmetric image, I have try using floor round ceiling to calculate the center offset, it is still off by 1-2 pixel, please help
Here's my implementation that run in the editor, place a quad and assign it to the renderer slot
 using UnityEngine;
 
 [ExecuteInEditMode]
 public class Test : MonoBehaviour
 {
     public bool reverseSign = true;
     public int size = 32;
 
     public float degree = 45;
     public float area = 0.5f;
 
     bool lastSign;
     int lastSize;
     float lastDegree;
     float lastArea;
 
     public Renderer renderer;
 
     void Update()
     {
         if (size != lastSize || degree != lastDegree || area != lastArea || reverseSign != lastSign)
             Execute();
 
         lastSign = reverseSign;
         lastSize = size;
         lastDegree = degree;
         lastArea = area;
     }
 
     void Execute()
     {
         var tempMaterial = new Material(renderer.sharedMaterial);
 
         var sizeX = size;
         var sizeY = size;
         Texture2D outputTex = new Texture2D(sizeX, sizeY, TextureFormat.ARGB32, false);
         var data = new float[sizeX, sizeY];
         Color32[] pixelArray = new Color32[sizeX * sizeY];
 
         for (int i = 0; i < sizeX; i++)
             for (int j = 0; j < sizeY; j++)
                 if (i >= sizeX * (1 - (area / 2 + 0.5))
                     && i < sizeX * (area / 2 + 0.5)
                     && j >= sizeY * (1 - (area / 2 + 0.5))
                     && j < sizeY * (area / 2 + 0.5))
                     data[i, j] = 1;
 
         data = ShearRotate(data, reverseSign ? -degree : degree);
 
         for (int j = 0; j < sizeY; j++)
             for (int i = 0; i < sizeX; i++)
                 pixelArray[i + j * sizeX] = new Color(data[i, j], 0, 0);
 
 
         outputTex.SetPixels32(pixelArray, 0);
         outputTex.Apply();
         outputTex.wrapMode = TextureWrapMode.Clamp;
         outputTex.filterMode = FilterMode.Point;
         tempMaterial.SetTexture("_MainTex", outputTex);
         renderer.sharedMaterial = tempMaterial;
     }
 
     float[,] ShearRotate(float[,] data, float degree)
     {
         var radian = degree * Mathf.PI / 180f;
         var sizeX = data.GetLength(0);
         var sizeY = data.GetLength(1);
         var alpha = -Mathf.Tan(radian / 2);
         var beta = Mathf.Sin(radian);
         //print("alpha: " + alpha + " beta: " + beta);
 
         var output = new float[sizeX, sizeY];
         ShearX(data, output, alpha, sizeX, sizeY);
         ShearY(output, data, beta, sizeX, sizeY);
         ShearX(data, output, alpha, sizeX, sizeY);
 
         return output;
     }
 
     float[,] ShearX(float[,] data, float[,] output, float shear, int sizeX, int sizeY)
     {
         int centerOffset = Mathf.FloorToInt((float)sizeY / 2 * shear);
         for (int y = 0; y < sizeY; y++)
         {
             var skew = shear * y;
             var skewi = Mathf.FloorToInt(skew);
             var skewf = skew - skewi;
             float oleft = 0;
             for (int x = 0; x < sizeX; x++)
             {
                 var pixel = data[x, y];
                 var left = pixel * skewf;
                 //var left = 0; //no anti alias
                 pixel = pixel - left + oleft;
                 var index = x + skewi - centerOffset;
                 if (index >= sizeX)
                     output[sizeX - 1, y] = pixel;
                 else if (index >= 0)
                     output[index, y] = pixel;
                 oleft = left;
 
             }
             var index2 = skewi + 1 - centerOffset;
             if (index2 >= sizeY)
                 output[sizeY - 1, y] = oleft;
             else if (index2 >= 0)
                 output[index2, y] = oleft;
         }
         return output;
     }
 
     float[,] ShearY(float[,] data, float[,] output, float shear, int sizeX, int sizeY)
     {
         int centerOffset = Mathf.FloorToInt((float)sizeX / 2 * shear);
         for (int x = 0; x < sizeX; x++)
         {
             var skew = shear * x;
             var skewi = Mathf.FloorToInt(skew);
             var skewf = skew - skewi;
             float oleft = 0;
             for (int y = 0; y < sizeY; y++)
             {
                 var pixel = data[x, y];
                 var left = pixel * skewf;
                 //var left = 0; //no anti alias
                 pixel = pixel - left + oleft;
                 var index = y + skewi - centerOffset;
                 if (index >= sizeY)
                     output[x, sizeY - 1] = pixel;
                 else if (index >= 0)
                     output[x, index] = pixel;
                 oleft = left;
 
             }
             var index2 = skewi + 1 - centerOffset;
             if (index2 >= sizeX)
                 output[x, sizeX - 1] = oleft;
             else if (index2 >= 0)
                 output[x, index2] = oleft;
 
         }
         return output;
     }
 }
 
              
               Comment
              
 
               
              Your answer