Entradas agregadas ‘Videojuegos’

Simulador de poda de frutales. 3D

[Vimeo 9400915]

El simulador de poda de frutales es una aplicación que hemos terminado recientemente, que se compone de dos partes principales, una de contenidos y otra de simulación. Fue realizada para el SEXPE, en concreto para el Centro de Formación Profesional de Don Benito, quienes necesitaban una aplicación con la que pudieran explicar a sus alumnos, de una manera práctica, cómo podar árboles frutales, sin tener que esperar a una estación del año en concreto.

Los trabajos comenzaron el año pasado y estamos acabando de implantar  la herramienta en las instalaciones de Don Benito, para que sus alumnos puedan empezar a utilizarla y aprender las diferentes técnicas de poda de frutales que se usan en la actualidad, al tiempo que podrán consultar información teórica, albergada en un apartado de contenidos.

El desarrollo de esta aplicación se ejecutó en diversas fases, la primera de ellas fue la de documentación, durante la cual contamos con la colaboración de un experto en poda que además de sus conocimientos prácticos, nos brindó valiosa información. También se utilizó bibliografía.

Una vez recopilada toda la documentación se dio paso a la siguiente fase, en la que se diferenciaron dos equipos. Uno de ellos era el encargado de la simulación, su finalidad era desarrollar una herramienta en 3d que simulara la poda de árboles frutales de pepita y hueso, durante sus tres primeros años, utilizando los tipos de poda más representativos: Poda de Producción y Poda de Formación (Palmeta y Vaso).

Unidad de Simulación:

Se trata de un mundo virtual en 3D, parecido a un videojuego, que representa un campo de árboles frutales. En él se pueden practicar los pasos más importantes de la poda, observando en directo su efecto sobre el crecimiento del árbol.

Para poder observar los efectos de la poda en el árbol, hemos desarollado un modelo de crecimiento, los árboles crecerán dependiendo de factores reales, hemos desarrollado un simulador de crecimiento de árboles

Éste tiene en cuenta tanto los cortes que hace el usuario como los efectos de la luz sobre el crecimiento del árbol, es decir que las ramas crecen en dirección de la luz. También se simula el efecto de sombras, asi que ramas que reciben poca luz van a crecer menos. Como todas las simulaciones , nuestro modelo sigue siendo una aproximación, dado a la complejidad de los procesos reales y a la necesidad de calcular el crecimiento de un árbol entero de la manera más rápida posible.

Para representar los árboles en 3D. Al final decidimos usar Panda3D, una 3D game engine desarollado por Disney para su línea de videojuegos que esta siendo mantenido y ampliado constantemente por Carnegie Mellon University. Panda3D puede ser usado con Python, lo que permite un desarollo facil y rápido, mientras sus funcionalidades de bajo nivel están implementadas en C, aumentando de esa manera la velocidad, un factor crucial para los videojuegos. La engine ofrece todo que se necesita para el desarollo de mundos 3D y videojuegos, grafos de escnea, I/O, audio, soporte de shaders, la posibilidad de importar modelos 3D de diferentes formatos (Blender, Maya, …), detection de colisiones y hasta física. También incluye herramientas de analisis de performance y una librería de widgets para crear interfacaces simples. No obstante, teniamos que integrar un par de cosas para tener toda la funcionalidad deseada, entre ellos una librería para poder utilizar la Wiimote de Nintendo y otro framework de widgets para integrar los datos de la parte teórica, que vienen en formato html.
La aplicación final ofrece en total 24 escenarios diferentes: dos tipos de poda (vaso y palmeta) del primer, segundo y tercer a√±o en cuatro especies de árboles frutales (melocotonero, manzano, ciruelo, peral). Las especies de árboles se distinguen tanto por sus propiedades de crecimiento como por su modelo visual.

Unidad de Contenidos:

Por su parte, el equipo de documentación se encargó de la producción de la parte de la herramienta destinada a la transmisión de la información teórica. En la que se plasmaron de manera didáctica diferentes contenidos propios de estos cursos.

Al terminar la fase de documentación, toda la información se organizó en un “árbol de contenidos”, formado por 3 bloques principales, divididos a su vez en tres temas cada uno:

  1. Conocimientos Previos: Morfología y Fisiología Frutal; Equipos y Herramientas de Poda y Principios Generales de Poda.
  2. Poda de Formación: Descripción; Formaciones en Volumen y Formaciones Planas.
  3. Poda de Producción: Descripción; Frutales de Hueso y Frutales de Pepita

Estos temas estaban compuestos por sus correspondientes contenidos, los cuales tienen tanto información teórica como gráfica, bien sean fotos o ilustraciones, dependiendo de lo que conviniera más al contenido en concreto.

Esta parte de la herramienta está destinada a la consulta por parte del alumno cuando practica con las simulaciones o en cualquier otro momento que necesite acceder a esta información.

En los próximos días esperamos poder liberar todo lo relacionado (estamos pendientes del permiso del promotor del proyecto) con la poda 3D

El curso de poda será liberado con licencia Creative Commons y el software con licencia aún por determinar pero en todo caso libre.

Publicaremos en el blog cuando esté disponible

febrero 13, 2010 at 8:43 am 23 comentarios

Gente Guada

Gente Guada ya va tomando forma, tenemos desarrollado el servidor, parte del cliente y la herramienta de configuración de avatares.

Este desarrollo es un juego colaborativo que estamos desarrollando para el SADESI (Sociedad Andaluza para el desarrollo de la Sociedad de la información), en poco tiempo se podrá jugar (final del verano) y ya estamos haciendo las primeras pruebas

Se ha desarrollado en python y se han programado varias librerías que pueden ser bastante útiles para otros propósitos aparte de este juego. Toda la información de desarrollo está en la wiki del proyecto en la forja de guadalinex.

WIKI

El juego se puede ya probar, simplemente hay que bajárselo de los repositorios y tener instalado python y pygame, en ese caso, el juego se verá en local.

REPOSITORIO

Aqui un minivídeo de Gente Guada en acción

Y los pantallazos.

pantallazo 1

julio 2, 2008 at 9:32 am 2 comentarios

Festival Nuevas Tecnologías de Extremadura de Los Santos de Maimona

Estuvimos por alli, lo pasamos muy bien, vimos muchas cosas interesantes y encima nos trajimos un par de premios por los dos videojuegos hechos en Software Libre para la Junta de Extremadura

noticia

Fue muy divertido y desde aqui agradecer a toda la gente del Ayuntamiento , organización y de la Fundación Maimona el trato hacia nosotros.

Esperamos volver el año que viene y participar más en este evento!

De nuevo gracias!

mayo 1, 2008 at 1:28 pm Deja un comentario

Primeras animaciones avatares de gente guada

abril 19, 2008 at 12:44 pm Deja un comentario

Pruebas de la baraja española 3D para el videojuego Ceibo

El videouego Ceibo sigue avanzando, estas son las primeras prubas de la baraja española libre en 3D que próximamente estará disponible .

Se han modelado en Blender y bueno, estos son la sota de copas y la de bastos.

copas.png

bastos.png

Un avance del juego se puede ver en (A veces está caido y a veces son versiones antiguas) : CEIBO

Más sobre el desarrollo del juego y el framework SWT en el blog de ceibo: BLOG DE CEIBO

febrero 22, 2008 at 11:39 am Deja un comentario

Creación de gráficos isométricos

En el mundo de los videojuegos existe una gran variedad de representaciones gráficas posibles, con variaciones importantes en cuanto a profundidad, grado de realismo, etc. Una de las más utilizadas desde los comienzos, tanto por la facilidad para su creación como por las proporciones de lo representado, es la perspectiva isométrica. Esta perspectiva situa la cámara del juego, o la vista del jugador, en un eje imaginario a 30 grados del suelo y enfocando el objetivo situado en el centro de los ejes de coordenadas (0,0,0 para un sistema tridimensional tí­pico) y representa los objetos con la misma proporción y tamaño, independientemente de la distancia a la que se encuentren del espectador. Este tipo de vista limita la sensación de profundidad, pero permite que el espectador aprecie todos los detalles de los modelos y se encuentre con un entorno mucho más simple, más asequible a la hora de jugar.

Isometrica

En varios de nuestros proyectos hemos decidido emplear este tipo de gráficos con un enfoque diferente: gráficos 2D generados a partir de objetos en 3D. Para ello, nos hemos servido del editor 3D Blender y de varios modelos ya creados en 3D.

En primer lugar, tras cargar el objeto del que queremos obtener los gráficos, indicamos a Blender el tipo de vista que queremos emplear. Para ello seleccionamos la cámara, y en el panel de edición (F9) activamos la opción “Ortographic”. Ahora, a fin de facilitar los cálculos de coordenadas y rotaciones, es aconsejable situar el modelo en el origen de coordenadas (0,0,0), y la cámara en un ángulo que permita visualizarlo (60,0,-45) y en una posición adecuada (por ejemplo (-5,-5,4.14), aunque estas coordenadas pueden necesitar ser cambiadas). Para acceder a la ventana de coordenadas y rotación de la cámara, la seleccionamos y pulsamos “N”.

Blender_iso_01

A fin de cuadrar el modelo en la captura de pantalla y reducir en lo posible el trabajo de edición, seleccionamos la escala a la que se mostrará el modelo. En el mismo panel de edición (F9), modificamos el valor de “Scale” hasta obtener el tamaño apropiado. Después, en el panel “Rendering” ajustamos los parámetros de la renderización de la imagen. Entre ellos, tamaño de la imagen (a ser posible, seleccionar el tamaño final del sprite para evitar tareas posteriores de redimensionado), tipo de imagen (PNG, JPG, BMP, etc), o directorio donde se almacenarán los resultados de las renderizaciones (por defecto, en “/temp”).

Una vez hecho esto, seguiremos siempre el mismo procedimiento para generar los gráficos. En primer lugar, situamos el modelo a fotografiar en el ángulo deseado mediante rotaciones en el eje Z (para un sistema isométrico con gráficos en 8 direcciones, lo situaremos en los valores de Z = 0,45,90,135,180,225,270,315). Tras situarlo en cada una de estas posiciones, realizamos una renderización (F12) y después almacenamos el gráfico creado (F3). En el caso de querer hacer un gif animado con varios movimientos del objeto, y suponiendo que este incluya un esqueleto con una serie de animaciones ya creadas, renderizamos mediante CTRL+F12 para obtener todos los frames del movimiento. Al finalizar, abrimos el primero de los frames con un editor de imágenes como GIMP (recordemos que, si no lo hemos modificado, las imagenes resultantes de las renderizaciones se almacenan en “/temp”), y arrastramos el resto de imágenes que compongan la animación a la imagen abierta del primer frame, de forma que cada una de las imágenes siguientes se situe como una capa nueva en la imagen.

Blender_iso_02

Después, seleccionamos la opción “Guardar como” para la imagen con todas sus capas, y en la ventana del explorador de archivos seleccionamos extensión .gif. En el panel siguiente seleccionamos “Guardar como animación”, y en el siguiente seleccionamos “Un cuadro por capa (reemplazar)”. Tras esto, GIMP realizará los cálculos necesarios y creará un gif animado 2D en base a un modelo 3D.

nina_walking

Bujaco

tMoctezuma

febrero 7, 2008 at 1:05 pm 2 comentarios

Montaje de un servidor de PlaneShift

Como paso necesario para la decisión del motor a utilizar, hemos instalado cada uno de los servidores para realizar una serie de pruebas. Quizá el que más facilidades daba en un principio (por incluir un tutorial extenso y bastante información) ha sido el que más problemas ha dado, PlaneShift, debido a que había algunos datos que no estaban incluidos en el tutorial y que si eran necesarios. Por ello, vamos a explicar de forma general lo incluido en el tutorial, indicando qué pasos son recomendables que no figuren ene ste. El tutorial seguido para instalar PlaneShift y sus compentes puede encontrarse en:

http://planeshift.cvs.sourceforge.net/*checkout*/planeshift/planeshift/docs/compiling.html

En primer lugar debemos descargar una serie de herramientas para la construcción y compilación de las librerías. Las herramientas y versiones requeridas son:

Jam – no especifica versión
libcURL – no especifica versión
SVN – no especifica versión
nVidia Toolkit – 1.5
MySQL – 5.0
WordNet – 2.1

Tras esto, tal y como nos indica el tutorial, deberemos descargar los componentes de PlaneShift, poniendo cuidado a las versiones utilizadas. Las versiones estables soportadas actualmente, que no son las indica el tutorial son las siguientes:

Cal3D – 493
CS – 28424
Cel – 3072
PlaneShift – última versión disponible

Si queremos instalar estas versiones directamente sin tener que bajar una anterior y luego actualizarla, empleamos:

svn co -r 493 svn://svn.gna.org/svn/cal3d/trunk/cal3d cal3d
svn co -r 28424 https://crystal.svn.sourceforge.net/svnroot/crystal/CS/branches/release/V1.2 cs
svn co -r 3072 https://cel.svn.sourceforge.net/svnroot/cel/cel/branches/release/V1.2 cel
svn co https://planeshift.svn.sourceforge.net/svnroot/planeshift/stable planeshift

Una vez hecho esto, antes de compilar nada, debemos acceder al archivo “configure.in” en el directorio “/home/sargas/development/cal3d” y comentar la linea 62 que incluye “AM_USE_UNITTESTCPP”. Para esto simplemente escribimos delante “dnl”, de forma que quedaría:

ANTES
61 # Check for unittest++
62 AM_USE_UNITTESTCPP

DESPUÉS
61 # Check for unittest++
62 dnl AM_USE_UNITTESTCPP

Tras esto podemos proceder a compilar el código siguiendo el tutorial. Es importante señalar que hay que cambiar la ruta de los directorios que sean necesarios sin seguir al pie de la letra el código del tutorial. Por ejemplo, en la orden

/home/user/development/cal3d$ ./configure –prefix=/home/user/development/cal3d

el directorio y la orden cambiarán dependiendo de dónde estemos instalando el motor. Por ejemplo, para el usuario “pepe”:

/home/pepe/development/cal3d$ ./configure –prefix=/home/pepe/development/cal3d

En el último paso de compilación de PlaneShift es muy importante incluir todo lo que vayamos a necesitar. Por ejemplo, para poder poner en funcionamiento el servidor, es necesario incluir también la orden de compilación de la base de datos de esta manera:

/home/user/development/planeshift$ jam -aq dbmysql server

Tras ejecutar todos los comandos para compilar las herramientas y asignar valores a las variables de entorno, copiamos los ficheros de arte de la forma indicada por el tutorial teniendo siempre en cuenta las condiciones de uso de estos.
Después deberemos crear la base de datos del servidor con las órdenes que se indican en el tutorial. Al menos la orden de start de la base de datos requiere acceso como root.

Una vez hecho esto, ya podremos poner en funcionamiento el servidor de PlaneShift. Es importante indicar que las variables antes exportadas no se guardan entre sesiones, por lo que antes de iniciar el servidor deberemos ajustarlas de nuevo:

export LD_LIBRARY_PATH=/home/pepe/development/cal3d/src/cal3d/.libs/:$LD_LIBRARY_PATH
export CRYSTAL=/home/pepe/development/cs
export CEL=/home/pepe/development/cel
./psserver

enero 10, 2008 at 11:02 am 2 comentarios

Motores: PlaneShift

En nuestro proceso de prueba y análisis de motores hemos elegido como segundo motor de pruebas el perteneciente a PlaneShift. Planeshift es un juego online de temática medieval fantástica con un mundo persistente, cuyo motor gráfico, basado en Crystal Space, representa las acciones en 3D con perspectiva de tercera persona. Su perspectiva y temática incluyen una serie de características (interacción con objetos, niveles o clases, soporte para misiones, hechizos, etc) que pueden ser bastante útiles de cara a implementar varias de las características de Gente Guada.

Los códigos fuente del servidor y el cliente del juego están bajo licencia GPL y pueden ser modificados sin problema, sin embargo todo el material audiovisual (arte, musica, diálogos, historias, modelos, etc) está bajo licencia propietaria y no puede ser empleado. Esto, aunque comprensible, podría retrasar el proyecto al tener que modelar todos los objetos y escenarios de nuevo. En cuanto al soporte, la comunidad de desarrolladores parece estar bastante activa y han elaborado tutoriales sobre el montaje de cliente y servidor, además de algunas características internas. Sin embargo, la reticencia de los desarrolladores a la creación de otros servidores de PlaneShift puede acarrear problemas y retrasar alguna parte del proyecto.

Aunque los gráficos y modelos que incluyen no podrán emplearse en nuestro proyecto, si nos sirven para hacernos una idea del potencial del motor. El motor emplea gráficos 3D en perspectiva isométrica con un corte realista. Los modelos reflejan con bastante fidelidad lo que pretenden representar, y aunque algunos detalles son mejorables, en general tienen bastante calidad.
El juego muestra a nuestro personaje en el centro de la pantalla en perspectiva de tercera persona, sin controles que posibiliten cambiar la posición de la cámara. Además, muestra en la zona superior varios botones con los que poder acceder a ventanas de inventario, registro de quest, libros de hechizos… botones que podrían ser eliminados o modificados para ajustarse a las necesidades de la aplicación. También encontramos en la zona inferior derecha la ventana de chat, la cual puede ocultarse si se desea.

En general el motor cumple la mayoría de los requisitos que buscamos para el proyecto Gente Guada: un motor gráfico que pueda mostrar elementos básicos, sistemas de colisiones, clases o grupos de personajes, sistemas de quest… sin embargo, contamos con los problemas de tener que crear todos los modelos, texturas, sonidos, etc desde cero, y los problemas de soporte que puedan surgir con los desarrolladores.

enero 10, 2008 at 9:05 am Deja un comentario

Efecto Niebla en Blender Game Engine

Uno de los mayores problemas que hemos encontrado a la hora de diseñar los distintos escenarios para el proyecto Extreventura reside en la profundidad de los escenarios exteriores. Esto es, el hecho de representar el infinito en las escenas que se desarrollan en el exterior. Así, encontramos distintas soluciones a dicho problema: la más simple de todas, crear un plano gigante y literalmente plasmar una foto de lo que pretendíamos que fuera el horizonte. Por otro lado, crear un horizonte de montaña, interponer objetos de forma disimulada para que el horizonte no se pudiera contemplar claramente, crear una niebla que nos oculte lo que existe más lejano que la distancia deseada… Esta última solución es que la que se explica en este documento. No conviene abusar de ella, porque resultaría bastante cargante y repetitivo, pero para algunas escenas exteriores, montañosas, laderas de río, realmente es una solución efectiva. Todo esto, claro está, si se usa un engine que no cuente con mejores soluciones. Por otro lado, si se desea también se puede modelar el horizonte, pero es una carga bastante innecesaria.

captura2.jpgCaptura 1

Como podemos ver en esta primera fotografía, existen dos efectos en esta fotografía. Primeramente, existe una niebla bastante densa grisácea, que nos impide ver correctamente la torre del fondo. Esta niebla, como podemos ver en la siguiente fotografia, se crea de una manera muy sencilla.

howto3.jpgCaptura 2

Activaremos el botón Mist, para que la niebla se procese. Los siguiente tres botones especifican la forma en la que queremos que la niebla se degrade cuando nos vamos alejando de ella. El valor Sta define donde queremos que comience la niebla, y el valor Di la distancia que debe de procesarse. Esto es, que los objetos que estén más lejos de Sta+Di no se van a ver. El valor Hi sirve para especificar como queremos que la niebla vaya desapareciendo con la altura. El valor Misi especifica la intensidad de la niebla. De esta manera ya tendremos el efecto de la niebla que podemos ver en la fotografía superior.

El efecto de cúmulos de humo que podemos ver en la foto es algo más complicado. Se explica a continuación de forma básica para no extendernos excesivamente. Quizás en otro post lo expliquemos de forma más detallada y sus posibles usos. En primer lugar, debemos crear en una capa que no sea la principal varios planos, en nuestro caso 2, con una textura semi-transparente que vaya a simular la textura del humo. Podemos verlas en la foto.

howto2.jpgCaptura 3

Como podemos ver, los dos planos humo1 y humo2 tienen la misma textura uv asociada, con los correspondientes botones Alpha activados. Esto es para que la textura muestre su transparencia.

howto4.jpgCaptura 4

Estos planos, humo1 y humo2, tienen asociados unos Logic Bricks que hará que se muevan en la dirección que nosotros queramos. En nuestro caso, hacia -Y. Para ello, asociamos unos sensores Always a unos Motion con el movimiento predefinido. Recordar que se debe activar la repetición de señal positiva en los sensores para que se repita el movimiento infinitamente. Esto hará que cuando se creen las partículas de humo, éstas se muevan en la dirección deseada.

A continuación, creamos un empty en la escena principal con unas curvas ipo asociadas que harán que el empty se mueva como nosotros queramos, para ir creando la niebla en los sitios que nosotros queramos. Este empty, de forma pseudo-aletoria va creando planos exactamente iguales a los que tenemos en la capa 2. Los planos creados están situados exactamente en la posición en la que actualmente se encuentra el empty, de ahí que tengamos las curvas ipo asociadas al empty, para que la posición en la que crea los planos no sea siempre exactamente la misma.

howto1.jpgCaptura 5

Como podemos ver en la captura adjunta, el empty tiene asociado varios Logic Bricks: por un lado, un sensor Always con un Actuator IPO que hará que la curva ipo de movimiento se ejecute infinitamente. Además, tiene asociados dos sensores Random unidos a dos Actuator Edit Object que hará que se creen partículas de humo continuamente. Los parámetros de los distintos sensores y actuator se pueden consultar en cualquier manual de Blender. Los más importantes en este caso son los valores Seed del sensor Random, que es la semilla de aleatoriedad, y el Valor Time en el Actuator Edit Object que será el tiempo de vida del objeto creado. Tened en cuenta que si se ponen tiempos de vida excesivamente grandes van a existir muchos objetos a la vez que afectarán al rendimiento de la escena.

El segundo efecto explicado es algo complicado conseguir efectos curiosos para la creación de niebla, aunque puede servir para otros muchos como puede ser humo de casas, humo de fuego, incluso fuego cambiando de manera adecuada las texturas de los planos, y tened en cuenta que aportan dinamismo a las escenas, paseos virtuales, que es algo muy importante para dar algo de vida a vuestras creaciones.

enero 8, 2008 at 12:54 am 3 comentarios

Motores: Second Life

El primero de los motores analizados son en realidad 2 motores: un motor para el lado servidor del juego (OpenSim), y otro para el lado cliente (SecondLife client). Para aquellos que no lo conozcan, SecondLife es un juego online con un mundo persistente donde el usuario puede interactuar de forma completa con su entorno, ya sea creando objetos, edificios o modificando el terreno de juego. Las acciones a las que tiene acceso el jugador y las opciones para los administradores están totalmente enfocadas a hacer de la interacción con otros jugadores el pilar principal del juego. Algo que casa con la idea central del proyecto Gente Guada.

La parte servidor, OpenSim, es un proyecto colaborativo en código abierto que trata de crear un programa servidor para Second Life. Aunque a primera vista parece encontrarse en una fase temprana de desarrollo, un vistazo al listado de actualizaciones y a la comunidad de desarrolladores lo desmienten. Problemas que nos hemos encontrado durante las pruebas han sido solucionado al poco tiempo de descubrirse, y las mejoras y arreglos parecen surgir a pasos agigantados. Este proyecto no intenta crear tan solo una copia del servidor de Second Life, sino modificarlo para darle la posibilidad de adaptar nuevas tecnologías al programa a medida que estas van surgiendo.

Por el lado del cliente nos encontramos con el cliente de Second Life portado a linux por los propios desarrolladores del juego. Actualmente se encuentra en una fase alpha y parece que el proyecto dista de llegar a una fase estable. Sin embargo, el hecho de contar con el equipo de Second Life como desarrolladores hace que el cliente sea más robusto de lo que debería ser una versión de este tipo, además de saber que existe una base sólida de código sobre el que trabajar.
En cuanto a su aspecto, este cliente muestra el mundo de Second Life exactamente igual que el cliente para Windows original. Es decir, un entorno 3D en perspectiva de tercera persona, modelado de forma realista, con un entorno que incluye controles sencillos y trata de ser accesible, buscando la simplicidad y el acceso facil antes que el preciosismo gráfico.

El conjunto de motores cliente y servidor no está tan desarrollado como sería deseable, aunque el hecho de contar con una base de desarrolladores tan fuerte lo compensa en parte. En cuanto a su funcionamiento, como mencioné antes, el juego está orientado en todos sus aspectos a que los jugadores interactuen entre si y formen comunidades, de forma que facilita bastante la creación del tipo de juego que es Gente Guada. En general, se adapta bastante a los requisitos que buscamos para un motor, aunque todavía está por ver si su estado de desarrollo junto con la comunidad que hay detrás supone una ventaja o un problema.

enero 2, 2008 at 12:53 pm Deja un comentario

Entradas antiguas


Categorías

Entradas recientes

Blog Stats

  • 47,199 hits

Seguir

Get every new post delivered to your Inbox.