Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Creating a Texture2D with code, Rotate

Discussion in 'Scripting' started by NewDeveloper, Jun 21, 2014.

  1. NewDeveloper

    NewDeveloper

    Joined:
    Aug 25, 2012
    Posts:
    153
    Hi guys
    I am working on a script which creates texture2d in gameplay, and in editor. The player selects how he wants the texture, and the script will create it, similar to what is used for Player Customization.
    I have already setted all textures to Advanced, Read and Write Enabled, and RGBA 32 or RGBA DXT in Import Settings.
    I have done a code which creates one texture from all selected, move and scale. Everything okay.
    But now the problem is when i need to rotate.
    I have seen on Wikipedia, and tried to create it.
    This is the code:
    Code (csharp):
    1.  
    2. Color[] cW = new Color[colors.Length];
    3. for (int c = 0; c < cW.Length; c ++) cW[c] = new Color (0, 0, 0, 0);
    4. for (int perEachY = 0; perEachY < texture.height; perEachY ++) {
    5.     for (int perEachX = 0; perEachX < texture.width; perEachX ++) {
    6.         Vector2 pos = new Vector2 (perEachX, perEachY);
    7.         Vector2 relPos = new Vector2 (pos.x - pivot.x, pos.y - pivot.y);
    8.         Vector2 rotPos = new Vector2 (relPos.x * Mathf.Cos (transforms[i].angle) - relPos.y * Mathf.Sin (transforms[i].angle),
    9.                                      relPos.x * Mathf.Sin (transforms[i].angle) + relPos.y * Mathf.Cos (transforms[i].angle));
    10.         Vector2 absPos = new Vector2 ((int) Mathf.Clamp (rotPos.x + pivot.x, 0, texture.width-1), (int)Mathf.Clamp (rotPos.y + pivot.y, 0, texture.height-1));
    11.         Debug.Log ("Point X: " + absPos.x + "; Point Y: " + absPos.y + "; Result = " + (((int) absPos.y) * texture.width + ((int) absPos.x)));
    12.         cW[((int) absPos.y) * texture.width + ((int) absPos.x)] = colors[perEachY * texture.width + perEachX];
    13.     }
    14. }
    15. colors = cW;
    16.  
    Now the problem is that when I rotate, it takes too much, that I had to decide to force close Unity3d, because it tool more then 20min.
    i have studied, that my Textures are all 1024x1024px, so the loop goes up to 1024^2, and the first time, I had assigned uncorrectly so it crashed at 830, and to work on 830 it took 5 secs.
    so it will take 830/(1024^2)*5 seconds for the hole texture.
    That is too much, I cannot make the player wait so much.
    I have seen Matrix4x4, but i am not sure how can I use it, because i would like to have a Matrix1024x1024, and Transform, Material has Matrix, but the Texture2D, doesn't.
    How I have to do this? Is there any another algorithm to use? or any another way? Will Matrix4x4 work? Wont Matrix4x4 take as much time?
    Thanks
    newDev
     
    Last edited: Jun 21, 2014
  2. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    You can increase performance by caching and stripping unnecessary method/property calls.

    Just as an example to speed your current code up a bit.

    Code (CSharp):
    1.  
    2. int colorLength = colors.Length;
    3. Color[] cW = new Color[colorLength];
    4.  
    5. int width = texture.width, height = texture.height;
    6.  
    7. // You dont need to initialize the values of this array since you effectivly assign the values of "colors" to it.
    8. //for (int c = 0; c < colorLength; c ++) cW[c] = new Color (0, 0, 0, 0);
    9.  
    10. for (int y = 0; y < height; y++) {
    11.     for (int x = 0; x < width; x++) {
    12.  
    13.         float angle = transforms[i].angle;
    14.         float sinAngle = Mathf.Sin(angle), cosAngle = Mathf.Cos(angle);
    15.         float relPosX = (float)x - pivot.x, relPosY = (float)y - pivot.y;
    16.  
    17.         float rotPosX = relPosX * cosAngle - relPosY * sinAngle, rotPosY = relPosX * sinAngle + relPosY * cosAngle;
    18.  
    19.         int absX = (int)Mathf.Clamp( rotPosX + pivot.x, 0, width-1 );
    20.         int absY = (int)Mathf.Clamp( rotPosY + pivot.y, 0, height-1 );
    21.  
    22.         cW[absY * width + absX] = colors[y* width + x];
    23.     }
    24. }
    25. colors = cW;
    26.  
    Furthermore, I've kicked out the Debug.Log, printing 1024^2 lines will take several minutes since Debug.Log is costy as hell.

    Additionally, you can do the Sin/Cos calculations and clamping yourself, which will get rid of those method calls aswell. Thats nothing more than manual inlining.

    As a rule of thumb, everything does cost performance. Therefore, get rid of method and property calls, storing values in variables, instantiating new types like vectors and generally try to reduce your code to the minimum. Try to do as much yourself in a cache friendly environment as possible.
     
  3. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    Repainting textures is not a good idea. Sometimes it's better to find a workaround that makes the same result.
     
  4. NewDeveloper

    NewDeveloper

    Joined:
    Aug 25, 2012
    Posts:
    153
    Sharp Development - Looks good,going to try.
    zaxvax - ya i know, I tried, but everything was difficult.
    As i have player can modify the character, just the texture, he can apply logos, shapes, colors, etc etc, PROIECTION was looking more difficult, and this was looking less difficult.
    I have tried, there is no problem when I do texture.GetPixels () or texture.SetPixels (), and also texture.Apply ().
    the problem is only this operation, move and scale works find, but rotate takes a lot.
     
  5. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Simply because of Mathf.Sin and Mathf.Cos. Thats why im saying, try to do the minimum needed.
     
  6. NewDeveloper

    NewDeveloper

    Joined:
    Aug 25, 2012
    Posts:
    153
    Ya thanks, but in each case it get heavy. I have resolved with using Matrix similar code.