Foros - Stratos

Programadores => Código de la Semana => Mensaje iniciado por: ethernet en 23 de Agosto de 2005, 05:52:54 PM

Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: ethernet en 23 de Agosto de 2005, 05:52:54 PM
 
(http://www.stratos-ad.com/forums/style_images/1/pip.gif)   Sistema de mapas de durezas mediante GDI de Windows (http://www.stratos-ad.com/forums/style_images/1/pip.gif)


Dim i As Long, Color As Long

i = Load_BitMap("dibujo.bmp") '// Carga la imagen en memoria y devuelve su identificador.

Color = GetPixel(i, 10, 5) '// Le el pixel x10 y5 de la imagen i.

Call Unload_BitMap(i) '// Descarga la imagen de la memoria.



El codigo en principio tiene que la ventaja de que se puede portar facilmente a otros lenguajes como C++ dada su sencillez ya que se apoya en funciones existentes en el API de Windows, tan solo habria que cambiar una llamada a una funcion intrinseca de Visual Basic, LoadPicture(), y el uso de un objeto propio de Visual Basic, el objeto Picture (no confundir con el control PictureBox) por la o las funciones pertinentes para cargar imagenes en memoria en formato BMP y las estructuras relacionadas que almacenen esos datos.

Es un codigo muy sencillo pero que pienso que puede ser util.
Podeis Descargar el código de aquí -> http://dxlib32.se32.com/private/regmap.zip


Salu2...

Autor: [EX3] - Josè Miguel Sánchez Fernández
[/list]

Si quieres enviar un código de la semana solo tienes que mandarlo a qualopec@gmail.com o por PM a ethernet.


Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 23 de Agosto de 2005, 07:04:15 PM
 siento decirte que el GetPixel del GDI de windows es la funcion mas lenta que puede existir, que conste que no es por pinchar ni nada, es la realidad
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: Lord Trancos 2 en 23 de Agosto de 2005, 07:39:27 PM
 coincido con zupervaca.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: ajmendoza en 23 de Agosto de 2005, 08:08:04 PM
 Pero es una aportación a quien  le pueda servir, y eso ya vale mucho.

Saludos.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: _Grey en 23 de Agosto de 2005, 08:19:42 PM
 Yo entiendo que: Load_Bitmap(), Unload_Bitmap() y GetPixel() ; son funciones creadas por el, no necesariamente las del API de win, todo y que seguro que tiene algunas detras,m pero ya es otra cosa.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 23 de Agosto de 2005, 08:35:34 PM
 yo es que me he bajado el codigo y lo he mirado antes para no meter la pata  :P  
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: ethernet en 23 de Agosto de 2005, 09:03:11 PM
 En mi opinión el punto fuerte de este COTW es la simplicidad que ofrece al programador. Estoy seguro que un montón de gente que empieza se ha preguntado miles de veces por qué no hay una función que me permita cargar una imagen y leer sus pixels sin tener que pelearte con el API de windows. En mi opinión pesa mucho más la simplicidad que la velocidad, quedando un resultado positivo.

Por mi parte yo tengo una clase que carga texturas y permite hacer lo mismo que especifica [EX3], además de aplicar algún filtro y hacer alguna operación más con ella (suma, resta, multiplicación...) etc. Ya la pondré como COTW.

Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 24 de Agosto de 2005, 12:57:55 AM
 
Cita de: "_Grey"Yo entiendo que: Load_Bitmap(), Unload_Bitmap() y GetPixel() ; son funciones creadas por el, no necesariamente las del API de win, todo y que seguro que tiene algunas detras,m pero ya es otra cosa.
Se referia al GetPixel() del API de Windows que utiliza mi funcion GetPixel(), que para no crear conflictos de nombres en el codigo con mi funcion la declaracion del API esta renombrada con un alias a GDIGetPixel() en el codigo.

Cita de: "zupervaca"siento decirte que el GetPixel del GDI de windows es la funcion mas lenta que puede existir, que conste que no es por pinchar ni nada, es la realidad
Estoy deacuerdo de que no es la funcion mas rapida que existe para leer pixeles, pero al menos es mil veces mas rapida que la que implemente en mi libreria, que entre lockear y deslockear las texturas o surfaces con D3D bajaba el rendimiento agresivamente hasta los 3fps leyendo 4 pixeles mientras que con el metodo a traves del GDI ni se inmuta casi el rendimiento leyendo 16 pixeles (como hecho de menos en D3D el veloz GetPixel() que trae DirectDraw)

El codigo esta diseñado para leer unos pocos pixeles en cada vuelta del bucle del juego sin que se vea severamente afectado el rendimiento del mismo ya que lo idee con la intencion de utilizarlo para leer mapas de durezas, cosa que preciso para mi proyecto. Me acorde de subir este codigo al cotw al responder una duda reciente sobre mapas de durezas que plantearon (link al post "Videojuego De Plataformas") y pense que podria ser util, como dice ethernet, para los que se inician en esto y buscan realizar algo tan simple como leer un pixel de una imagen.

Salu2...
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 24 de Agosto de 2005, 03:50:47 AM
 si quieres ganar velocidad con los surfaces de direct3d o directdraw obligale a que lo lea en memoria, al hacer el bloqueo lo mas seguro que este bajando la textura por el agp o el pci-express siempre, no obstante la forma mas correcta es metiendo el mapa de durezas en la propia ram del ordenador y accediendo a ella como un tozo de memoria mas.

saludos
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 24 de Agosto de 2005, 11:15:55 PM
 
Cita de: "zupervaca"si quieres ganar velocidad con los surfaces de direct3d o directdraw obligale a que lo lea en memoria, al hacer el bloqueo lo mas seguro que este bajando la textura por el agp o el pci-express siempre
Te refieres a almacenar las texturas y surfaces en memoria RAM mediante uno de estos dos flags?

CitarEnum CONST_D3DPOOL
    D3DPOOL_DEFAULT        = 0
    D3DPOOL_MANAGED        = 1
    D3DPOOL_SYSTEMMEM      = 2
    D3DPOOL_SCRATCH        = 3
End Enum
Me da que esto no me iba a solucionar mucho, ya que el problema radica en que en D3D, al menos como me han enseñado a mi y como he visto en varios ejemplos, tienes que copiar en un array los datos de la textura que quieres leer o escribir, y para ello hay que lockear, copiar, deslockear, y esto es algo lento y se nota si haces varias entradas a diferentes o la misma superficie.

Cita de: "zupervaca"no obstante la forma mas correcta es metiendo el mapa de durezas en la propia ram del ordenador y accediendo a ella como un tozo de memoria mas.
En teoria el metodo del GDI si no me equivoco lo hace por RAM y supongo que el GetPixel() del GDI no tendra que lockear, ni copiar memoria de alli para aca, ni deslockear para leer la informacion de una imagen, posiblemente sea por ello por lo que sea mas rapido que en D3D. Ahora, si alguien conoce un metodo mucho mas rapido y optimo con D3D estare encantado de poder echarle un ojo :) (asi que ya sabes, ethernet, espero ansioso tu cotw (ole))

Salu2...
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 25 de Agosto de 2005, 12:25:34 AM
 veamos el GetPixel del api de win32 tiene que funcionar para muchos formatos de color, desde 1bit a 32bits y lo hace todo la misma funcion ademas de que estas llamando a una dll por cada llamada a GetPixel, si con este no lo ves claro dejo el tema, por que una funcion inline hace maravillas en bucles tochos como puede ser las comprobaciones de mapas de durezas y si ademas el formato siempre es de 8bits mas rapido aun ya que se puede hacer mediante rotaciones

saludos
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 25 de Agosto de 2005, 04:02:17 PM
 
Cita de: "zupervaca"veamos el GetPixel del api de win32 tiene que funcionar para muchos formatos de color, desde 1bit a 32bits y lo hace todo la misma funcion ademas de que estas llamando a una dll por cada llamada a GetPixel, si con este no lo ves claro dejo el tema, por que una funcion inline hace maravillas en bucles tochos como puede ser las comprobaciones de mapas de durezas y si ademas el formato siempre es de 8bits mas rapido aun ya que se puede hacer mediante rotaciones
Vale, D3D son varias dlls y sigue realizando mas pasos para leer 4 bytes que lo que hace GetPixel() del GDI y programarme "inline" en VB6 una funcion de lectura de pixeles a pelo para leer surfaces de D3D (MAP_GetPixel() o SURF_GetPixel() de mi libreria) o simplemente en una estructura de datos como usa el GDI para los BMP haria que fuese mucho mas lenta que GetPixel() del GDI (sencillamente por el lenguaje), si con esto no lo ves claro dejo el tema por que veo que no me sigues :P

[EDIT] Lo mas que podria mirar con D3D seria probar hacerme unas funciones que cargaran las superficies y las dejaran lockeadas permanentemente para realizar las lecturas, que esto seria mas rapido ya que solo tendria copiar una sola vez la textura al array, pero pre-supongo que esto haria mucho gasto de memoria, me equivoco? [/EDIT]

Salu2...
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 25 de Agosto de 2005, 04:11:10 PM
 haz lo que quieras, cada vez me doy mas cuenta de realmente no hay nivel por estos foros

saludos

editado: rectifico, no es que no haiga nivel, es mas bien que no quieren aprender
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: fiero en 25 de Agosto de 2005, 05:04:49 PM
 zupervaca tio, creo que sabes mucho, pero a veces te pones muy testarudo :rolleyes: . Simplemente EX3 trabaja en VB, es distinta forma de trabajar que la que tienes tú. Tú zupervaca nunca harías un juego en VB simplemente porque pensarías que hay una forma más rápida, y claro que la hay, C++ ó asm. Pero hay gente que le gusta trabajar a otro nivel, sin tratar con buffers de memoria ni nada de eso, trabajando simplemente con las imagenes y un Getpixel de toda la vida, cosa que veo totalmente factible. Y ahora no me ataques a mi, que mi Getpixel son cuatro lineas de ensamblador  :P .

En cuanto lo que comenta EX3 de velocidades, puedo comentar mi caso. Yo renderizo con mis propias funciones en ensamblador y sólo utilizo DX o GDI para crear las superficies de renderizado. Pues he comprobado que me va más rápido (unos poquillos FPS) utilizando GDI. La razón es que con GDI creo un BITMAP que me hace de backbuffer y no necesito realizar algunas funciones de DX como Lock y UnLock, ya que el bitmap permanece siempre en la misma zona de memoria.

Saludos y buen rollo, [yo si creo que por aquí hay nivel...]
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 26 de Agosto de 2005, 12:11:10 AM
 
Cita de: "zupervaca"haz lo que quieras, cada vez me doy mas cuenta de realmente no hay nivel por estos foros

saludos

editado: rectifico, no es que no haiga nivel, es mas bien que no quieren aprender
Siento desilusionarle, "maestro" :P, pero no puedes pretender que todo el mundo haga las cosas como tu piensas que deben ser. Lo bonito de este mundo es que haya variedad y que la gente eliga que le interesa usar, habra quien prefiera complicarse y apurar al maximo logrando un resultado impecable que zoza la perfeccion... y habra quienes prefieren acortar trabajo y lograr lo que buscan en corto plazo sacrificando algo de potencia y eficacia.

Aplaudo tu impetu con intentar alcanzar la perfeccion en tus codigos. Mis codigos no seran lo mas rapidos del mundo pero si me permiten realizar mis ideas en corto espacio de tiempo y logrando unos resultados mas que aceptables, al menos para mi, suficientes para quedarme satisfecho con lo que hago.

Y eso de que no quieren aprender... 6 años me he tirado aprendiendo VB sin tener muchas nociones en metodologia de programacion, aprendiendo y probando multitud de funciones del API de Windows que pudiese aprovechar para mis proyectos y aprendiendo DirectX, su api grafico mas a fondo que el resto de librerias y que aun sigo aprendiendo. El fruto a sido la mierda de libreria que tengo colgada en mi web que no sera la mas eficiente del mundo pero que si permite que cualquiera haga cosas vistosas y con unos resultados decentes sin mucho esfuerzo en una mierda pero sencillo y lento lenguaje como es VB y que mucha gente, al igual que yo, usamos y que de por si mismo no da mucho si que digamos. Siendo esto asi significa que he cumplido con mi objetivo y me siento satisfecho de mi trabajo y de mis horas invertidas en el.

Dicho todo esto espero que entiendas de una vez por todas cual es objetivo de mis codigos, de mis aportaciones, el de hacer facil lo que para muchos es casi imposible, lo que se supone que se busca con el COTW, y no el de lograr la perfeccion. A ver si de ahora en adelante podemos evitar berrinches similares a este y respetar un poco el trabajo de los demas, aunque no tengan un "level" de tu agrado :P

Salu2... ;)

P.D.: Aunque no te lo parezca agradezco y valoro tus consejos como hago con los del resto, siempre son bienvenidos.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: ethernet en 26 de Agosto de 2005, 01:00:26 AM
 No critico a la gente que trata de optimizar su código al máximo, pero está claro que para conseguir cosas importantes no es necesario, ___ni de lejos__, optimizar demasiado. Voy a poner los dos ejemplos que siempre pongo. Glest está programado en C++ usando OpenGL para renerizar, si mirais su código no es lo más óptimo del mundo, usa excepciones y me juego todo el dinero del mundo a que no todos sus algortimos son lo más óptimo, sin embargo ahí tienes GLEST por su versió 1.2 (sí, de hoy mismo :)) y con un MOD desarrollándose. El otro ejemplo es Haddd, un motor en C#, un lenguaje que lleva mil capas por debajo, etc, etc... y creo que poco hay que decir de Haddd, todos hemos visto su calidad.

A medida que maduras un poco te das cuenta que la optimización es un parte que debes tener en cuenta mucho depués de que tengas cierta experiencia a la hora de llevar a cabo proyectos, que es cuando tienes una visión global de una aplicación y es cuando de verdad puedes optimizar :). Hay algunos que hemos optado por ir por el camino de la eficiencia y no de la efectividad, esto es, queremos hacer juegos y no códigos muy rápidos, pero tb muy aislados.

En cualquier caso el COTW sirve precisamente para discutir un trozo de código y son muy enriquecedoras todas las aportaciones,  siempre y cuando vayan por el camino correcto y no por el que nos lleva a la descalificación y a las generalizaciones, que molestan tanto como inciertas son.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: _XUTI_H_ en 04 de Septiembre de 2005, 11:29:32 PM
 Este es el primer mensaje q escribo en este foro,
y si no pongo las etiquetas como toca y todo eso espero q me disculpeis. ;)

El tema de las durezas no creo q pueda traer tanta tela.
La idea (q pienso q es lo importante) es q un podamos dibujar un bitmap como una capa sobre una imagen, y que la podamos interpretar por separado para detectar colisiones!!!!

Entender estas cosas y saber aplicarlas es lo que, en mi modesta opinión, permite que existan los videojuegos, y q cada vez haya más gente q se dedique a aprender este mundo.

Cada uno comienza con lo q puede y como puede. Yo puedo llegar a avengorzarme al ver código q he escrito hace seis meses, pensando q ahora lo haria mejor ... pero si no hubiera hecho ese código hace medio año, ahora no podria realizarlo mucho mejor.

Alabo la labor de quien dedica horas a aprender, y a enseñar lo que aprende a otros como él.

Y finalmente, [EX3] si quieres realmente optimizar tus librerias guardando en RAM los bytes del mapa de durezas y accediendo con tus funciones, enviame un mensaje y te hecho una mano y las lineas de código que hagan falta.

Adew
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: ethernet en 05 de Septiembre de 2005, 12:20:52 AM
Cita de: "_XUTI_H_"El tema de las durezas no creo q pueda traer tanta tela.
aquí nos lo tomamos todo muy a pecho, lo entenderás cuando lleves más tiempo XD

Ya sabes que puedes enviarme un código si lo consideras útil para que lo publique y lo podamos discutir o tirarnos los trastos a la cabeza, según se vea.

un saludo
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 05 de Septiembre de 2005, 02:46:17 AM
 
Cita de: "_XUTI_H_"El tema de las durezas no creo q pueda traer tanta tela.
La idea (q pienso q es lo importante) es q un podamos dibujar un bitmap como una capa sobre una imagen, y que la podamos interpretar por separado para detectar colisiones!!!!
Planteaselo a un novato o recien iniciado y a ver que te dice. Que para nosotros "ahora" nos parezca sencillo no quiere decir que para otros lo sean ;)

Cita de: "_XUTI_H_"Y finalmente, [EX3] si quieres realmente optimizar tus librerias guardando en RAM los bytes del mapa de durezas y accediendo con tus funciones, enviame un mensaje y te hecho una mano y las lineas de código que hagan falta.
Mi unico problema con guardar o no las texturas en RAM es si me conviene sobre cargar la RAM de texturas pudiendo guardarlas en la memoria de la tarjeta dejando la RAM disponible para otras tareas. Y aun asi, para evitar esa perdida de velocidad solo tendria que dejar "lockeadas" las superficies y almacenar la informacion de sus pixeles en un array en memoria cuando cargo las superficies para poder acceder a ellas sin tener que:Todo esto cada vez que accedo a ellas para leer un simple pixel. Pierdo velocidad por realizar demasiados pasos en cada llamada a la funcion que me puedo ahorrar una vez cargada la superficie en memoria. Aun asi gracias por la ayuda :)

Salu2...
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: Grugnorr en 05 de Septiembre de 2005, 07:28:35 AM
 Sin entrar en los flames:

a) Cargar en memoria un bitmap para leer un pixel y descargarlo me parece excesivo, intenta cachearlo.

B) Cuando cargues el mapa de durezas, pásalo a un array de bytes y haz tu lógica sobre él, será muucho más rápido.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: zupervaca en 05 de Septiembre de 2005, 12:11:17 PM
Cita de: "Grugnorr"Sin entrar en los flames:

a) Cargar en memoria un bitmap para leer un pixel y descargarlo me parece excesivo, intenta cachearlo.

B) Cuando cargues el mapa de durezas, pásalo a un array de bytes y haz tu lógica sobre él, será muucho más rápido.
no insistas, yo ya se lo dije unas cuantas veces y ni caso hijo :P

saludos
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: _XUTI_H_ en 06 de Septiembre de 2005, 01:31:31 AM
 
Citar
Planteaselo a un novato o recien iniciado y a ver que te dice. Que para nosotros "ahora" nos parezca sencillo no quiere decir que para otros lo sean

Ei, d trankis! Lo que queria decir es que lo principal es que se capte la idea! Te estaba intentando defender un poquete delante de los "fanáticos de la optimización". Jeje (ahora no os piqueis los demás conmigo ;-)  )

[Ex3] el tema que t creo q todo el mundo quiere decir es que, VALE, crea tu mapa de durezas como un bitmap en el photoplof si quieres. Guardaló como un BMP ...

... pero no lo vas a dibujar!!!!. X tanto NO NECESITAS crear una superficie de vram ni nada de ese estilo. Solo tienes que leer el valor de los pixels que forman el dibujo de tus durezas y determinar si existe o no la colisión.

Un Bitmap no és más que una serie de pixeles, por tanto SOLO has de leer el valor del pixel deseado, y la forma más ràpida para este tipo de operaciones es alojar en memoria principal estos datos. NO te hace falta gastar funciones del palo de GetPixel ni obtener acceso a superficies de VRAM.

Una forma efectiva (suponiendo un mapa de durezas de, por ejemplo, 8 bits de profundidad) es cargar el bitmap (usando funciones de de bindous pa C++, no sé exactamente como se haria en VB, ho sent :( ) y obtener un puntero (char*) al inicio de estos datos.
De manera que el primer elemento al que apunta este puntero (puntero[0]) serà el pixel 0,0 de tu bitmap, el segundo (puntero[1]) seria el pixel 1,0, y así sucesivamente.

Para acceder a la posicion (3,8) ?????
la Fommula mágica --> pos = xPos + yPos*ancho = 3 + 8*ancho. (donde ancho es la anchura del bitmap). Y ahora obtenemos puntero[pos] y yatà, el valor correcto de nuestro pixel.
PERO!!!, este valor (si estamos en 8 bits como deciamos) recuerda que es el valor del color de paleta del pixel, no el RGB ni el COLOREF ni nada parecido. Para obtener el color real has de acceder a la paleta de tu bitmap con el valor de puntero[pos] y obtendrás el valor real de tu pixel.

Bueno, supongo que tampoco lo explicado demasiado bien. Intentaré hacer una pequeña libreria con un par de utilidades de este tipo. Lo que no puedo garantizar es que lo pueda hacer en VB (creo que lo he gastado un par de veces solo). Y me miraré las funciones estas de manejo de Bitmaps que hace mil que no las gasto!

Citar
a) Cargar en memoria un bitmap para leer un pixel y descargarlo me parece excesivo, intenta cachearlo.

Por cierto, d que hablais cuando decis lo de "cahear". Me molaria saber si hay trucos para accesos más rápidos cuando gastais un mapa de durezas o cosas parecidas, me muero por aprender!!!!

Wueno, saludos a todos. Adew.
Título: Sistema De Mapas De Durezas Mediante Gdi De Window
Publicado por: [EX3] en 06 de Septiembre de 2005, 04:13:44 AM
 
Cita de: "Grugnorr"a) Cargar en memoria un bitmap para leer un pixel y descargarlo me parece excesivo, intenta cachearlo.
Err, creo que no me explique bien xD Me referia que como en cada lectura de pixel la funcion que actualmente tengo implementada hacia una copia en un array del contenido de la superficie, se leia el pixel y despues se destruia el array (el array era local en la funcion) decia de hacer que en la funcion de carga copiar los datos en un array global y alojarlo en memoria hasta que se quiera descargarlo, pero la funcion solo cargaria la superficie en la memoria y despues de copiarse los datos se descargaria, manteniendo el array en memoria, vamos, que todo lo que hace la funcion actual hacerlo solo en el inicio. Resumiendo, en cuestion es a lo que os referis, alojar en memoria simplemente un array con los valores de los pixeles.

El por que tengo esta implementacion en la libreria es por que las funciones de lectura/escritura estaban pensadas en un principio para poder leer/escribir pixeles en mitad de la ejecucion del programa para  modificar texturas y de paso para usarse para el tema de mapas de durezas.

Salu2...