Foros - Stratos

Proyectos => Jad Engine => Mensaje iniciado por: en 24 de Febrero de 2005, 01:13:12 PM

Título: Pregunta Técnica Sobre C#
Publicado por: en 24 de Febrero de 2005, 01:13:12 PM
 Bien, mi pregunta es la siguiente, estoy haciendo un cargador de ficheros bsp de quake3 usando como base el motor Hadd, pero cargo casi todo pero cuando llego a cargar los lightmap que están en una zona del fichero bsp, no lo hago correctamante, me podrías ayudar?

Os explico brevemente como se hace en c++ para ver como se haría en c#

se emplea esta estructura:

struct tBSPLightmap
{
   byte mapaDeBits[128][128][3]; // Datos RGB en una imagen de 128x128  
};


   // Buscamos las estructuras de los lightmaps en el archivo
   fseek(fp, bloques[kLightmaps].desplaz, SEEK_SET);

   // Los recooremos todos y los leemos
   for(i = 0; i < m_iNumDeLightmaps; i++)
   {
      // Leemos los valores rgb para cada lightmap
      fread(&lightmap, 1, sizeof(tBSPLightmap), fp);

      // Creamos un lightmap de 128x128 por cada estrucutura q haya
      CrearTexturaLightmap(i,lightmap.mapaDeBits, 128, 128);
   }


Bien, yo logro cargar los lightmaps pero no los logro pasar correctamente a un jagged array del tipo [128][128][3]

A ver si os animais y me ayudais.

Gracias de antemano.
Título: Pregunta Técnica Sobre C#
Publicado por: Haddd en 24 de Febrero de 2005, 01:33:51 PM
 Mírate en la ayuda BinaryReader

Título: Pregunta Técnica Sobre C#
Publicado por: BeRSeRKeR en 24 de Febrero de 2005, 04:16:13 PM
 Yo utilizaba un array unidimensional de bytes. Aunque realmente ese array sólo lo utilizaba en tiempo de carga ya que lo que se mantenía era un array de texturas de Direct3D.

Así, para acceder a los pixels del lightmap en el array de bytes hacía:

for (i = 0; i < m_iNumLightMaps; i++)
{
   for (j = 0; j < 128 * 128; j++)
   {
       float r = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 0)];
       float g = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 1)];
       float b = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 2)];
   }
}


Como los lightmaps de quake3 eran de 128x128 y 24 bits por pixel, LIGHTMAP_BLOCK es:

#define LIGHTMAP_BLOCK    (128 * 128 * 3)

De todas formas sí es cierto que también deberías poderlo hacer con ese tipo de arrays. ¿El resto de datos del BSP sí los puedes leer bien?.

Saludos.
Título: Pregunta Técnica Sobre C#
Publicado por: zupervaca en 24 de Febrero de 2005, 06:07:35 PM
 buenas, he visto este codigo y no es que este mal, pero podria optimizarse y realizar menos operaciones matematicas, no te lo tomes a mal ber  ;)

for (i = 0; i < m_iNumLightMaps; i++)
{
  for (j = 0; j < 128 * 128; j++)
  {
      float r = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 0)];
      float g = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 1)];
      float b = (float)lightmaps[i * LIGHTMAP_BLOCK + (j * 3 + 2)];
  }
}

mejor seria asi

z = 0;
for (i = 0; i < m_iNumLightMaps; i++)
{
  for (j = 0; j < 128 * 128; j++)
  {
      float r = (float)lightmaps[z]; z++;
      float g = (float)lightmaps[z]; z++;
      float b = (float)lightmaps[z]; z++;
  }
}

no se si el c# puedes manejar punteros ya que si es asi se podria optimizar muchos mas ahorrandos resolver la direccion numerica del array haciendolo directamente con el puntero

sobre el tema del post, mira ver si el problema lo tienes en las segundas coordenadas de texturas y no al leer los lightmaps

saludos a todos
Título: Pregunta Técnica Sobre C#
Publicado por: BeRSeRKeR en 24 de Febrero de 2005, 06:14:05 PM
 No me lo tomo a mal pero como es algo que se realiza en tiempo de carga pues no me preocupé de hacerlo con punteros (esa parte es de un motor que hicimos ProD y yo hace mucho tiempo).

Saludos.
Título: Pregunta Técnica Sobre C#
Publicado por: en 24 de Febrero de 2005, 07:05:38 PM
 Bien como veo que hay nivel, entonces vayamos al meollo, el problema no es que no lo lea, sino que al aplicarlo a una textura me falla, lo he pasado a una textura normal, para ver si obtenía bien la imagen y ahí es donde me doy cuenta que no lo hago correctamente, voy a pasar a poner todo mi código y a ver si alguien me puede ayudar a encontrar mi fallo, ok?

'Declaración del struct
public struct tBSPLightmap
{
  public byte[] mapaDeBits; //(128 * 128 * 3) Datos RGB en una imagen de 128x128
}


           // Buscamos las estructuras de las texturas light map en el archivo
           if (m_iNumDeLightmaps>0)
           {
               //Si hay texturas se lightmaps las creo.
               m_pLightmap = new Texture[m_iNumDeLightmaps];
           }
           //Ahora procedo a leerlas del fichero.
           fs.Seek((long)bloques[(int)eBloquess.kLightmaps].desplaz, SeekOrigin.Begin); //Me posiciono dentro del archivo.
           for (int i = 0; i < m_iNumDeLightmaps; i++)
           {
               //Leo los valores de mi light maps.                
               lightmap.mapaDeBits = r.ReadBytes(128*128*3);                
               
               // Creamos un lightmap de 128x128 por cada estrucutura q haya
               CrearTexturaLightmap(i, lightmap.mapaDeBits, 128, 128);
           }


Y ahora os escribo la función CrearTexturaLightmap:


       public void CrearTexturaLightmap(int indice, byte[] pMapaDeBits, int ancho, int alto)
       {
           CambiarGamma(pMapaDeBits, ancho, alto, 9f); //Aquí se podrá usar una variable global para cambiar la gamma de todas las texturas de light map.
           m_pLightmap[indice] = new Texture(device, ancho, alto, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
           int[] buffer = new int[ancho * alto];
           GraphicsStream gs = null;
           gs = m_pLightmap[indice].LockRectangle(0, LockFlags.None);


           for (int x = 0; x < ancho; x++)
           {
               int offset = x * ancho;
               for (int y = 0; y < alto; y++)
               {
                   byte r = pMapaDeBits[offset + y * 3 + 0];
                   byte g = pMapaDeBits[offset + y * 3 + 1];
                   byte b = pMapaDeBits[offset + y * 3 + 2];
                   byte a = 255;
                   buffer[offset + y] = (a << 24 | r << 16 | g << 8 | B);
               }
           }

           gs.Write(buffer);
           m_pLightmap[indice].UnlockRectangle(0);
       }


Aclaración, CambiarGamma sólo hace eso, no tiene nada especial.

Sobre el formato de las imágines ya se que son R5G6B5, pero eso es igual, pues yo la cambio en tiempo real al formato A8R8G8B8, decir, que si uso el formato origal tb falla.

Es decir, el fallo es que la imagen que obtengo no es la correcta.

Y bueno, decir tb que efectivamente la logré cargar en un jagged array de [128][128][3], leyendo byte a byte del fichero binario, pero como me fallaba igual, pues lo cambie por este otro sistema, en definitiva de ambas formas me carga la textura mal, es como si al leer los bytes y ponerlos en la imagen resultante no lo hicise en su sitio.

A ver si alguien me hecha un cable, que la verdad es que me tiene ese detalle muy atrancado.

Gracias de antemano.
Título: Pregunta Técnica Sobre C#
Publicado por: en 24 de Febrero de 2005, 07:15:50 PM
 Me estoy imaginando una cosa y ese será el problema.

Esas texturas de 128 x 128 cada una de ellas lleva varias imágenes de lightmap distribuidas o deben de llevar una sólo, es que es posible que me funcione correctamente y al visionarla me crea que no.

Título: Pregunta Técnica Sobre C#
Publicado por: en 24 de Febrero de 2005, 07:18:35 PM
 Y ya puestos a preguntar quizás lo que no haga correctamente sea al cargar el estado de mi dispositivo para pintar texturas y texturas de lightmap. Este sería mi uso.

           // Especificamos los estados de render y texture-stages que necesitamos
           device.RenderState.AlphaBlendEnable = false;
           device.RenderState.AlphaSourceBlend = Blend.SourceAlpha;
           device.RenderState.DestinationBlend = Blend.One;
           device.RenderState.AlphaTestEnable = false;
           
           device.RenderState.FillMode = FillMode.Solid;
           device.RenderState.CullMode = Cull.CounterClockwise;
           device.RenderState.Lighting = false;
           
           device.RenderState.ZBufferEnable = true;
           device.RenderState.StencilEnable = true;
           device.RenderState.Clipping = true;
           device.ClipPlanes.DisableAll();
           device.RenderState.VertexBlend = VertexBlend.Disable;
           device.RenderState.IndexedVertexBlendEnable = false;
           device.RenderState.FogEnable = false;

           device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;
           device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
           device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
           device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
           device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse;
           device.TextureState[0].AlphaOperation = TextureOperation.Disable;
           device.TextureState[0].TextureCoordinateIndex = (int)TextureCoordinateIndex.PassThru;
           device.TextureState[0].TextureTransform = TextureTransform.Disable;
           
           device.TextureState[1].ColorOperation = TextureOperation.Modulate;
           device.TextureState[1].TextureCoordinateIndex = (int)TextureCoordinateIndex.PassThru;
           device.TextureState[1].AlphaOperation = TextureOperation.Disable;
           device.TextureState[1].ColorArgument1 = TextureArgument.TextureColor;
           device.TextureState[1].ColorArgument2 = TextureArgument.Current;

           device.SamplerState[0].MinFilter = TextureFilter.Linear;
           device.SamplerState[0].MagFilter = TextureFilter.Linear;
           device.SamplerState[0].MipFilter = TextureFilter.Linear;
           device.SamplerState[1].MinFilter = TextureFilter.Linear;
           device.SamplerState[1].MagFilter = TextureFilter.Linear;
           device.SamplerState[1].MipFilter = TextureFilter.Linear;

           device.SamplerState[0].AddressU = TextureAddress.Wrap;
           device.SamplerState[0].AddressV = TextureAddress.Wrap;

Es posible que no lo haga correctamente?
Título: Pregunta Técnica Sobre C#
Publicado por: zupervaca en 24 de Febrero de 2005, 07:18:50 PM
 comprueba que al incrementar el rojo, verde o azul en la correccion del gama no te pases de 255 ya que si se pasa da "la vuelta", el factor de la gama te recomiendo ponerla en 3 o 4 para que se acerque al de kake3  ;)


ej: si rojo > 255 entons rojo = 255

saludos
Título: Pregunta Técnica Sobre C#
Publicado por: BeRSeRKeR en 24 de Febrero de 2005, 07:24:46 PM
 En cada uno de esos sets de lightmaps de 128x128 hay muchos lightmaps empaquetados.
Título: Pregunta Técnica Sobre C#
Publicado por: masaniz en 24 de Febrero de 2005, 07:34:51 PM
 Gracias berseker entonces los lightmaps los cargo bien.

Y zuperbaca el código que uso para cambiar la gamma es el siguiente:
       public void CambiarGamma(byte[] pImagen, int ancho, int alto, float factor)
       {
           for (int x = 0; x < ancho; x++)
           {
               for (int y = 0; y < alto; y++)
               {

                   float scale = 1.0f, temp = 0.0f;
                   float r = 0, g = 0, b = 0;

                   r = (float)pImagen[x + y + 0];
                   g = (float)pImagen[x + y + 1];
                   b = (float)pImagen[x + y + 2];

                   r = r * factor / 255.0f;
                   g = g * factor / 255.0f;
                   b = b * factor / 255.0f;

                   if (r > 1.0f && (temp = (1.0f / r)) < scale) scale = temp;
                   if (g > 1.0f && (temp = (1.0f / g)) < scale) scale = temp;
                   if (b > 1.0f && (temp = (1.0f / B)) < scale) scale = temp;

                   scale *= 255.0f;
                   r *= scale; g *= scale; b *= scale;

                   pImagen[x + y + 0] = (byte)r;
                   pImagen[x + y + 1] = (byte)g;
                   pImagen[x + y + 2] = (byte)b;
               }
           }
       }


Y sobre los estados estoy un poco liado sobre todo por este parámetro:

device.TextureState[1].TextureCoordinateIndex = (int)TextureCoordinateIndex.PassThru;

Si pongo eso hace cosas raras, alguien me dijo que usase esto otro
device.TextureState[1].TextureCoordinateIndex = 1
así sale bien, pero los colores no me gustan, o sale verdoso, azulado, no se, me hace cosas raras.
Título: Pregunta Técnica Sobre C#
Publicado por: masaniz en 24 de Febrero de 2005, 07:48:33 PM
 Disculparme por mi ignoración, pero la función CambiarGamma no la cambie del tutorial que estoy siguiente de c++ y trasapasando a c# (pa aprender un poquillo :-)) y ahora la he cambiado por esta otra que he elaborado, pues fallaba ahí:

       public void CambiarGamma(byte[] pImagen, int ancho, int alto, float factor)
       {
           for (int x = 0; x < ancho*alto*3; x+=3)
           {
               float scale = 1.0f, temp = 0.0f;
               float r = 0, g = 0, b = 0;

               r = (float)pImagen[x + 0];
               g = (float)pImagen[x + 1];
               b = (float)pImagen[x + 2];

               r = r * factor / 255.0f;
               g = g * factor / 255.0f;
               b = b * factor / 255.0f;

               if (r > 1.0f && (temp = (1.0f / r)) < scale) scale = temp;
               if (g > 1.0f && (temp = (1.0f / g)) < scale) scale = temp;
               if (b > 1.0f && (temp = (1.0f / B)) < scale) scale = temp;

               scale *= 255.0f;
               r *= scale; g *= scale; b *= scale;

               pImagen[x + 0] = (byte)r;
               pImagen[x + 1] = (byte)g;
               pImagen[x + 2] = (byte)b;
           }
       }


Pero aún así me gusataría saber bien lo de los estados del dispositivo los valores más correctos en c#.

Gracias de nuevo

Y cuando aprenda un poquito más pues intentaré colaboraros en algo.
Título: Pregunta Técnica Sobre C#
Publicado por: ethernet en 24 de Febrero de 2005, 08:01:06 PM
 Donde esté la aritmética de punteros que se quiten los indexados guarros. Supongo que C# no tiene punteros.. :P
Título: Pregunta Técnica Sobre C#
Publicado por: zupervaca en 24 de Febrero de 2005, 08:08:42 PM
 los estados de texturas los pones bien, basicamente dejas los de directx por defecto, lo unico decirte que desactives el 1 y solo lo actives cuando es necesario ya que aunque indiques que no tiene textura, al dejarlo activado las directx realizaran mas operaciones que si lo desactivaras.

como ultimo consejo te recomiendo que hagas un interface para los cambios de estado del device para no realizar tantas llamadas a los objetos com de directx
Título: Pregunta Técnica Sobre C#
Publicado por: BeRSeRKeR en 24 de Febrero de 2005, 08:56:52 PM
 Me ha entrado el gusanillo así que he hecho un cargador de BSPs del quake3 utilizando el motor C# y he probado a visualizar los lightmaps como textura D3D sobre un polígono y éste es el resultado:

(http://www.arrakis.es/~jonathan01/stratos/d3dlmaps.jpg)

Este es el lightmap en formato "raw" que he visualizado con el Photoshop:

(http://www.arrakis.es/~jonathan01/stratos/lightmap04.jpg)

Este es el código utilizado:

private void LoadLightmaps()
{
       file.Seek(header.lumps[Q3LUMP_LIGHTING].offset, SeekOrigin.Begin);

       numLightmaps = header.lumps[Q3LUMP_LIGHTING].len / LIGHTMAP_BLOCK;

       byte[] lightmaps = reader.ReadBytes((int)(LIGHTMAP_BLOCK * numLightmaps));

       // Escribe los lightmaps en formato raw
       for (int i = 0; i < numLightmaps; i++)
       {
               FileStream fOut = new FileStream("lightmap0" + i + ".raw", FileMode.Create);
               int offset = (int)LIGHTMAP_BLOCK * i;
               fOut.Write(lightmaps, offset, (int)LIGHTMAP_BLOCK);
               fOut.Close();
       }

       OutputLightmaps(lightmaps);
}

public void OutputLightmaps(byte[] lightmaps)
{
       lmTextures = new Texture[numLightmaps];

       int pixel = 0;
       for (int i = 0; i < numLightmaps; i++)
       {
               lmTextures[i] = new Texture(Haddd.Video.Device, 128, 128, 1, Usage.None, Format.X8R8G8B8, Pool.Managed);

               int pitch;
               GraphicsStream gs = lmTextures[i].LockRectangle(0, LockFlags.Discard, out pitch);

               for (int j = 0; j < 128 * 128; j++)
               {
                       byte r = lightmaps[pixel++];
                       byte g = lightmaps[pixel++];
                       byte b = lightmaps[pixel++];
                       byte a = 255;

                       gs.WriteByte(b);
                       gs.WriteByte(g);
                       gs.WriteByte(r);
                       gs.WriteByte(a);
               }

               lmTextures[i].UnlockRectangle(0);
       }
}


Fíjate que a la hora de guardar el pixel del lightmap lo hago en el orden BGRA.

Saludos.
Título: Pregunta Técnica Sobre C#
Publicado por: masaniz en 25 de Febrero de 2005, 12:50:55 PM
 Ok Berseker, ya veo, efectivamente esa textura coincide con las que yo cargo, pero hacía determinadas cosas que por eso creía que el fallo era al cargarlas.

Veo que has optimizado más el código que yo puse, pues yo transformaba todo en un int haciendo operaciones con los bits y tal y como tu lo has hecho mejora el sistema, pues escribes los bytes directamente con lo que no hace falta ninguna operación adicional salvo escribirlos en orden inverso. Muy buena optimización.

Ahora seguriré con el resto de cosas que se han de cargar a ver si termino el cargado y os lo paso para que veais como queda, y hombre si alguien quiere optimizar algo pues mejor que mejor.

Ya veo que hay buen nivel por aquí, eso mola :-D

Salud2
Título: Pregunta Técnica Sobre C#
Publicado por: zupervaca en 25 de Febrero de 2005, 01:42:25 PM
 solo una cosa mas y es que procura crear las texturas en el mismo formato que has creado el device, es decir, si el device tiene el formato X8R8G8B8 haz las texturas en ese mismo si no te ira mas lento ya que las directx hacen una conversion oculta para el programador
Título: Pregunta Técnica Sobre C#
Publicado por: masaniz en 01 de Marzo de 2005, 11:34:45 AM
 gracias zupervaca, no lo sabía.