Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Girar array[] "X" grados

Iniciado por juanma_teso, Diciembre 18, 2017, 01:12:08 AM

Tema anterior - Siguiente tema
Hola a todos! Hace varios meses me enrolé en un proyecto, hemos ido avanzando pero por el camino he tenido problemas que decidí dejar de lado para poder seguir con algo nuevo, este es uno de esos problemas, resulta que tenía que modificar una textura para hacer que una parte sea transparente con un fade; de 100%-0% de manera lineal, hasta aquí todo OK, pero luego me pidió que se pudiera rotar esta textura y este fade, me tiré toda una mañana para conseguir que rotara el fade y solo conseguí que rotara 90º  en fin, más adelante se me ocurrió rotar el array entero pero me parece una solución muy mala, por eso acudo a vosotros a ver si alguno se le ocurre una forma de pasarle "120" grados y esté correctamente rotada, porque en este momento parece que estuviera "30" grados (creo, hace mucho le hice cambios y no recuerdo el resultado exacto).
 
 
 

public static Texture2D ObtenerGradiente (Texture2D textura, int _angulo)
{
   int desfase, angulo;
   desfase = (_angulo < 90) ? 0 : (_angulo < 180) ? 1 : (_angulo < 270) ? 2 : 3;
   angulo = _angulo - desfase * 90;
   Gradient gradiente = new Gradient ();
   GradientColorKey[] keyColores = new GradientColorKey[] {
   new GradientColorKey (Color.white, 0),
   new GradientColorKey (Color.white, 0)
   };
   GradientAlphaKey[] keyAlfas = new GradientAlphaKey[] {
   new GradientAlphaKey (1, 0),
   new GradientAlphaKey (0, 1)
   };
   gradiente.SetKeys (keyColores, keyAlfas);
   Color[] colores = textura.GetPixels ();
   int numero = 0;
   Color c;
   Debug.Log (textura.width + " x " + textura.height);
   for (int x = 0; x < textura.width; x++) {
      for (int y = 0; y < textura.height; y++) {
         xdim = Mathf.Sin (angulo * Mathf.Deg2Rad) * ((float)x / (float)textura.width);
         ydim = Mathf.Cos (angulo * Mathf.Deg2Rad) * ((float)y / (float)textura.height);
         c = colores [x * textura.width + y];
         c.a = gradiente.Evaluate (xdim + ydim).a;
         colores [x * textura.width + y] = c;
      }
   }
   Debug.Log ("Bucle finalizado");
   Texture2D resultado = new Texture2D (textura.width, textura.height);
   resultado.SetPixels (colores);
   resultado.Apply ();
   return resultado;
}

 
 

Diciembre 18, 2017, 05:10:55 AM #1 Ultima modificación: Diciembre 18, 2017, 05:15:08 AM por lightbug
Interesante problema, esto está lejos de ser una solución, pero jugueteando un rato logré que si le cambias el punto de referencia de donde le asignas la amplitud a esos senos y cosenos podés lograr un barrido, pero este va de 0% de gradiente a 50% gradient, o por ahí. Este código probé, como el tuyo pero saque lo de los desfasajes y el gradient de código para poner uno public y modificarlo desde inspector en un OnGUI. (Fijate que las x e y dim las cambie de nombre, era para entenderlo más pero bueno, me olvidé de reacomodarlas). Lo unico que hice fue cambiar el "centro" a la hora de normalizar con la línea:
 
(x - (float)textura.width/2) / textura.width;
 
(y - (float)textura.height/2) / textura.height;
 

public Texture2D ObtenerGradiente (Texture2D textura )
{
   float angulo = m_angulo;      
   Color[] colores = textura.GetPixels ();
   Color c;
   Debug.Log (textura.width + " x " + textura.height);
   for (int x = ; x < textura.width; x++) {
      for (int y = ; y < textura.height; y++) {
         
         float xCursor = (x - (float)textura.width/2) / textura.width;
         float yCursor = (y - (float)textura.height/2) / textura.height;
         xCursor = Mathf.Sin (m_angulo * Mathf.Deg2Rad) * xCursor;
         yCursor = Mathf.Cos (m_angulo * Mathf.Deg2Rad) * yCursor;
                     
         c = colores [x * textura.width + y];
         c.a = m_gradiente.Evaluate ( (xCursor + yCursor)).a;
         colores [x * textura.width + y] = c;
      }
   }
   Debug.Log ("Bucle finalizado");
   Texture2D resultado = new Texture2D (textura.width, textura.height);
   resultado.SetPixels (colores);
   resultado.Apply ();
   return resultado;
}

 
y esto me dio:
 

 
osea, lo hace desde el centro, podés ver donde los Evaluás respecto al gradient, me olvidé de eso, quizás luego de normalizar me olvidé de alguna constante o algo.
 
Aunque rota y todo no queda el gradiente de punta a punta.

Cita de: gZone date=1513561269No la estás girando desde el eje...
   
   
      Por cierto ¿no le sirve rotar el objeto en vez de la textura?
   


No porque la textura va a un material que tiene más elementos... esa fue la primera solución que intenté
 
Y sobre lo del eje, si te refieres al centro tienes razón, el eje en el array era el punto (0,0), o sea una de las esquinas... (y según leo puede ser la solución)
 
Cita de: lightbug date=1513570255Interesante problema, esto está lejos de ser una solución, pero jugueteando un rato logré que si le cambias el punto de referencia de donde le asignas la amplitud a esos senos y cosenos podés lograr un barrido, pero este va de 0% de gradiente a 50% gradient, o por ahí. Este código probé, como el tuyo pero saque lo de los desfasajes y el gradient de código para poner uno public y modificarlo desde inspector en un OnGUI. (Fijate que las x e y dim las cambie de nombre, era para entenderlo más pero bueno, me olvidé de reacomodarlas). Lo unico que hice fue cambiar el "centro" a la hora de normalizar con la línea:
   
   
      (x - (float)textura.width/2) / textura.width;
   
   
      (y - (float)textura.height/2) / textura.height;
   
   

public Texture2D ObtenerGradiente (Texture2D textura )
{
   float angulo = m_angulo;      
   Color[] colores = textura.GetPixels ();
   Color c;
   Debug.Log (textura.width + " x " + textura.height);
   for (int x = ; x < textura.width; x++) {
      for (int y = ; y < textura.height; y++) {
         
         float xCursor = (x - (float)textura.width/2) / textura.width;
         float yCursor = (y - (float)textura.height/2) / textura.height;
         xCursor = Mathf.Sin (m_angulo * Mathf.Deg2Rad) * xCursor;
         yCursor = Mathf.Cos (m_angulo * Mathf.Deg2Rad) * yCursor;
                     
         c = colores [x * textura.width + y];
         c.a = m_gradiente.Evaluate ( (xCursor + yCursor)).a;
         colores [x * textura.width + y] = c;
      }
   }
   Debug.Log ("Bucle finalizado");
   Texture2D resultado = new Texture2D (textura.width, textura.height);
   resultado.SetPixels (colores);
   resultado.Apply ();
   return resultado;
}

   
      y esto me dio:
   
   
      
   
   
      osea, lo hace desde el centro, podés ver donde los Evaluás respecto al gradient, me olvidé de eso, quizás luego de normalizar me olvidé de alguna constante o algo.
   
   
      Aunque rota y todo no queda el gradiente de punta a punta.
   


Cambiar el punto sobre el que rota! No se me había pasado por la cabeza, voy a probar, muchas gracias por dedicarle algo de tiempo, en la miniatura se puede como efectivamente está rotada; por cierto, si no haces un cast a float hace cálculos con enteros y por eso quedan franjas en la imagen grande, sobre que va hasta la mitad del gradiente no habría problema si asigno el los valores a 0.5 del gradiente

Cita de: juanma_teso date=1513602756si no haces un cast a float hace cálculos con enteros y por eso quedan franjas en la imagen grande
   


ahh, puede que se me haya pasado algo, igual si tenés un término int y el otro float el int se convierte a float para hacer la operación, el resultado es float, o por lo menos siempre me dio/imprimió un float, por eso el cast se lo puse solo al width/height ya que tenía la división entre ints, en x o y no era necesario y el resultado era el mismo (el fade). El tema de las franjas, fijate como está el gradiente, muy ajustado lo usé, quizás no era el mejor ejemplo para mostrar.
 
El tema del "punta a punta" seguro tiene algun que otro truquillo, probá con el "Evaluate", incrementar el argumento quizás(?).

no deberias rotar el array, deberias tener una funcion q te regrese el punto q necesites "rotado"... si comienzas a rotar el array iras perdiendo precision en los calculos

@lightbug tienes razón! A ver si mañana a la mañana puedo seguir con esto...
 
Cita de: Braltor date=1513617576no deberias rotar el array, deberias tener una funcion q te regrese el punto q necesites "rotado"... si comienzas a rotar el array iras perdiendo precision en los calculos
   


Al final no he rotado el array, pero no pillo lo del punto rotado, dices de hacer una función y llamarla desde el bucle??

Holas!!!
 
no puedes rotar las uvs?? es mas barato seguro en texturas grandes y no te tienes que pelear con arrays, lo puede haces por script o mejor aun si puedes por shader que seria lo mas rapido.
 

public void RotateUVs(float radians)
    {
        MeshFilter mf = this.GetComponent<MeshFilter>();
        Vector2[] uv = mf.mesh.uv;
 
        float c = Mathf.Cos(radians);
        float s = Mathf.Sin(radians);
        Vector2[] rotMatrix = new Vector2[2];
            rotMatrix[0] = new Vector2(c, -s);
            rotMatrix[1] = new Vector2(s, c);
        Vector2 uvPivot = new Vector2(0.5f, 0.5f);
        for (int j = 0; j < uv.Length; j++)
        {
            uv[j] = uv[j] - uvPivot;
            float u = rotMatrix[0].x * uv[j].x + rotMatrix[0].y * uv[j].y + uvPivot.x;
            float v = rotMatrix[1].x * uv[j].x + rotMatrix[1].y * uv[j].y + uvPivot.y;
            uv[j].x = u;
            uv[j].y = v;
        }
        mf.mesh.uv = uv;
    }

 
Por shader no lo he probado,puede que haya algo mal escrito,pero diria que tiene que ser asi
 
 
 

void vert(inout appdata_full v)
{
  float s = sin(_radians);
  float c = cos(_radians);
  float2x2 rotationMatrix = float2x2(c, -s, s, c);
  float2 uvPivot = float2(0.5, 0.5);
  v.texcoord.xy = mul(v.texcoord.xy - uvPivot, rotationMatrix) + uvPivot;
}

 
 

Cita de: hammer date=1513636073Holas!!!
   
   
      no puedes rotar las uvs?? es mas barato seguro en texturas grandes y no te tienes que pelear con arrays, lo puede haces por script o mejor aun si puedes por shader que seria lo mas rapido.
   
   

public void RotateUVs(float radians)
    {
        MeshFilter mf = this.GetComponent<MeshFilter>();
        Vector2[] uv = mf.mesh.uv;
 
        float c = Mathf.Cos(radians);
        float s = Mathf.Sin(radians);
        Vector2[] rotMatrix = new Vector2[2];
            rotMatrix[0] = new Vector2(c, -s);
            rotMatrix[1] = new Vector2(s, c);
        Vector2 uvPivot = new Vector2(0.5f, 0.5f);
        for (int j = 0; j < uv.Length; j++)
        {
            uv[j] = uv[j] - uvPivot;
            float u = rotMatrix[0].x * uv[j].x + rotMatrix[0].y * uv[j].y + uvPivot.x;
            float v = rotMatrix[1].x * uv[j].x + rotMatrix[1].y * uv[j].y + uvPivot.y;
            uv[j].x = u;
            uv[j].y = v;
        }
        mf.mesh.uv = uv;
    }

   
      Por shader no lo he probado,puede que haya algo mal escrito,pero diria que tiene que ser asi
   
   
       
   
   

void vert(inout appdata_full v)
{
  float s = sin(_radians);
  float c = cos(_radians);
  float2x2 rotationMatrix = float2x2(c, -s, s, c);
  float2 uvPivot = float2(0.5, 0.5);
  v.texcoord.xy = mul(v.texcoord.xy - uvPivot, rotationMatrix) + uvPivot;
}

   
       
   


Lo voy a probar también, el tema de shaders y materiales me trae de cabeza, eso me lo pasa el diseñador/modelador/jefe, pero como no tiene ni idea de Unity tengo que encargarme yo de este tipo de cosas... como diría Joaquín "No sé lo que es un UV Hulio"

Etiquetas: