orden de dibujo isométrico con imágenes de mosaico más grandes que simples: ¿algoritmo de orden de dibujo?

8

Tengo un mapa isométrico sobre el que coloco varias imágenes. La mayoría de las imágenes caben en un único mosaico, pero algunas imágenes son ligeramente más grandes. Por ejemplo, tengo una cama de azulejos de tamaño 2x3.

Esto crea un problema al dibujar mis objetos en la pantalla, ya que algunos mosaicos se superponen erróneamente con otros mosaicos.

Las dos soluciones que conozco son dividir la imagen en segmentos de mosaico 1x1 o implementar mi propio algoritmo de orden de dibujo, por ejemplo, asignando un número a cada imagen. La imagen con el número 1 se dibuja primero, luego 2, 3, etc.

¿Alguien tiene consejos sobre lo que debo hacer?

Me parece que dividir una imagen isométrica no es muy obvio. ¿Cómo decides qué partes de la imagen están 'en' un mosaico en particular? Tampoco puedo permitirme dividir todas mis imágenes manualmente.

El algoritmo de orden de dibujo parece una mejor opción, pero no estoy seguro de si será fácil de implementar. No puedo resolver, en mi cabeza, cómo lidiar con situaciones en las que cambias el índice de una imagen, lo que causa un efecto de impacto en muchas otras imágenes. Si alguien tiene recursos / tutoriales sobre esto, estaría muy agradecido.

Roger Smith
fuente

Respuestas:

3

Lo que necesitas se llama algoritmo de pintor.

Desea dibujar primero el mosaico más alejado, incluidos los doodads o caracteres en él.

Luego dibuje el siguiente más cercano y repita hasta que termine.

Sus objetos que abarcan más de un mosaico deben tener un punto de ancla / origen declarado. Esta es la celda de cuadrícula que, cuando se dibuja, dará como resultado que también se dibuje su objeto más grande. El punto de origen se elige para que se dibuje después de que todas las celdas en las que se sangra el objeto se dibujen primero.

Según su pregunta, su punto de origen será el mosaico más cercano a la cámara. (Si está utilizando fichas cuadradas, en lugar de mosaicos con forma de diamante, se debe elegir la ficha inferior izquierda o inferior derecha).

Código de ejemplo para una cuadrícula cuadrada. Modifique la dirección del bucle para su cuadrícula de diamantes.

for(int y = 0; y < GridHeight; ++y) {
    for(int x = GridWidth - 1; x > -1; --x) {
        MapCell cell = getMapCell(x,y);
        DrawTerrain(cell);
        if(cell.IsDoodadOrigin){
            DrawDoodad(cell);
        }
        if(cell.IsCharacterOrigin){
            DrawCharacter(cell);
        }
    }
}
Jim
fuente
¿No veo cómo puede funcionar esto? Imagine una cama de 2x3 rodeada completamente de cajas. Al iterar a través de las celdas, cuando llegue al 'origen' del objeto más grande, ya habrá dibujado cuadros que deberían estar detrás y delante de la cama.
Wozza
Tienes razón, esta técnica funcionará para cuadrículas cuadradas. También funcionará para cuadrículas diagonales que usan doodads / caracteres cuadrados. No funcionará para la forma irregular de 2x3 en una cuadrícula diagonal.
Jim
3

Divide tus objetos en cubos de 1 × 1 × 1, asignando a cada cubo una imagen de las partes del objeto que estarían físicamente en ese cubo.

Esto es fácil si comienza con objetos 3D reales y los reduce a 2D. Si está dibujando sus objetos directamente en 2D (o si tiene arte existente que necesita dividir), se requiere un esfuerzo manual. Afortunadamente, la división no necesita ser exacta, siempre y cuando se asegure de que ninguna de las partes de la imagen asignadas a un cubo dado se derrame fuera del área hexagonal que cubriría un cubo sólido de 1 × 1 × 1 en esa posición. Puede ser útil hacer una superposición que muestre los contornos de cada cubo como una capa adicional en su editor de gráficos.

Luego, solo asigna una prioridad a cada cubo como p = x + y + z (suponiendo que las tres coordenadas aumenten hacia la cámara) y renderiza los cubos en orden ascendente por prioridad.


Aquí hay un ejemplo rápido basado en esta imagen de Wikimedia Commons (por Phasmatinox / Allefant , usado bajo la licencia CC-By-SA 3.0 ):

        Proyección isométrica de un objeto extendido dividido en cubos.

La cómoda de la imagen ocupa dos fichas, y he dibujado los límites de esas fichas (los hexágonos rojos) encima. Las partes de la imagen que se encuentran dentro de cada hexágono deben asignarse al mosaico correspondiente; la parte donde se superponen los hexágonos se puede asignar a cualquiera de los mosaicos (o incluso a ambos, si lo desea), ya que la elección no afectará el resultado final.

Tenga en cuenta que es posible que necesite elaborar este algoritmo simple si puede tener varios objetos en una baldosa, paredes / pisos entre baldosas u objetos (como personas) que se mueven suavemente entre baldosas. Las paredes y los pisos son bastante simples de manejar: se pueden dibujar en cualquier punto después del contenido del mosaico que están delante (desde el punto de vista de la cámara) y antes del mosaico que están detrás. Esta también es una regla práctica útil para los objetos que se mueven entre mosaicos; trátelos como si fuera un muro entre esos azulejos.

En cuanto a los objetos múltiples en un mosaico, a veces son bastante simples: por ejemplo, si tuviera un libro sobre el cofre en la imagen, obviamente debería dibujarse después de la superficie en la que se encuentra. Sin embargo, las cosas pueden volverse más complicadas si, por ejemplo, tienes objetos en los que las personas pueden sentarse. Por ejemplo, si una persona estaba sentada en un banco, de espaldas a la cámara, entonces el cuerpo de la persona debe dibujarse después del banco, pero sus piernas (que están detrás del banco de la cámara) deben dibujarse antes. Una solución, en este caso, sería dividir las piernas de una persona sentada en un componente separado con su propia posición (ya sea en el mosaico adyacente o entre los mosaicos).

Ilmari Karonen
fuente
1

Puede ayudarlo a particionar sus objetos por tipo o por altitud. Por ejemplo, el paisaje (pisos, paredes) debe dibujarse antes que los objetos (camas). Además, debido a la perspectiva isométrica, las fichas de menor altitud deben dibujarse antes que las de mayor altitud.

Además, si opta por la numeración de índices (ordenamiento Z, realmente), le recomiendo usar espacios entre los números: no haga sus pisos 1y su cama 2. Use algo como suelos = 10y camas = 20o 100algo más, para que pueda "insertar" cosas en el medio sin aumentar el dominó.

cenizas999
fuente
Planeo hacer lo que sugieres en el primer párrafo. El problema que tengo es que los objetos de un tipo similar se superponen incorrectamente. Por ejemplo, mi cama se superpone a la mesita de noche. Sin embargo, estaba sugiriendo que le diera a cada instancia de una imagen un número diferente, no dando a todas las camas el número 20, por ejemplo.
Roger Smith
Depende. ¿Qué pasa si tienes dos camas una al lado de la otra? Una forma en que la gente suele evitar esto es agregar objetos en el orden en que deberían dibujarse, pero no sé si eso lo ayudará.
cenizas999
1
Si dos camas están una al lado de la otra, entonces la cama que tiene el valor y más alto se debe dibujar sobre la otra. Si son la misma coordenada y, entonces la que tiene el valor x más alto (suponiendo que la parte superior del mapa es (0,0).
Roger Smith