ordem de desenho isométrica com imagens maiores que uma única peça - algoritmo de ordem de desenho?

8

Eu tenho um mapa isométrico sobre o qual coloco várias imagens. A maioria das imagens cabe em um único bloco, mas algumas são um pouco maiores. Por exemplo, eu tenho uma cama de tamanho 2x3 azulejos.

Isso cria um problema ao desenhar meus objetos na tela, pois alguns blocos se sobrepõem erroneamente a outros.

As duas soluções que eu conheço estão dividindo a imagem em segmentos de bloco 1x1 ou implementando meu próprio algoritmo de ordem de desenho, por exemplo, atribuindo um número a cada imagem. A imagem com o número 1 é desenhada primeiro, depois 2, 3 etc.

Alguém tem conselhos sobre o que devo fazer?

Parece-me que dividir uma imagem isométrica não é muito óbvio. Como você decide quais partes da imagem estão em um bloco específico? Também não posso me dar ao luxo de dividir todas as minhas imagens manualmente.

O algoritmo de ordem de desenho parece uma escolha melhor, mas não tenho certeza se será fácil de implementar. Não consigo resolver, na minha cabeça, como lidar com situações em que você altera o índice de uma imagem, o que causa um efeito colateral em muitas outras imagens. Se alguém tiver recursos / tutoriais sobre isso, ficaria muito grato.

Roger Smith
fonte

Respostas:

3

O que você precisa é chamado algoritmo de um pintor.

Você deseja desenhar o bloco mais distante primeiro, incluindo os doodads ou caracteres nele.

Em seguida, desenhe o próximo mais próximo e repita até terminar.

Seus objetos que abrangem mais de um bloco devem ter um ponto de ancoragem / origem declarado. Essa é a célula da grade que, quando desenhada, resultará em seu objeto maior também sendo desenhado. O ponto de origem é escolhido para ser desenhado depois que todas as células para as quais o objeto sangrar são desenhadas primeiro.

Com base na sua pergunta, seu ponto de origem será o bloco mais próximo da câmera. (Se você estiver usando ladrilhos quadrados, em vez de ladrilhos em diamante, o ladrilho inferior esquerdo ou inferior direito deve ser escolhido.)

Código de exemplo para uma grade quadrada. Altere a direção do loop para sua grade de diamante.

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
fonte
Não estou vendo como isso pode funcionar? Imagine uma cama 2x3 cercada completamente por caixas. Ao percorrer as células, quando você atingir a 'origem' do objeto maior, você já teria desenhado caixas que deveriam estar atrás e na frente da cama.
Wozza 5/12/12
Você está correto, esta técnica funcionará para grades quadradas. Também funcionará para grades diagonais que usam caracteres / rabiscos quadrados. Não funcionará para a forma 2x3 irregular em uma grade diagonal.
Jim
3

Divida seus objetos em cubos 1 × 1 × 1, atribuindo a cada cubo uma imagem das partes do objeto que estariam fisicamente nesse cubo.

Isso é fácil se você estiver começando com objetos 3D reais e renderizando-os em 2D. Se você estiver desenhando seus objetos diretamente em 2D (ou se tiver arte existente que precise ser dividida), será necessário algum esforço manual. Felizmente, a divisão não precisa ser exata, desde que você garanta que nenhuma das partes da imagem atribuídas a um determinado cubo seja derramada fora da área hexagonal que um cubo sólido 1 × 1 × 1 nessa posição cobriria. Pode ser útil fazer uma sobreposição mostrando os contornos de cada cubo como uma camada extra no seu editor de gráficos.

Em seguida, basta atribuir uma prioridade a cada cubo como p = x + y + z (assumindo que as três coordenadas aumentam em direção à câmera) e renderizar os cubos em ordem crescente por prioridade.


Aqui está um exemplo rápido baseado nesta imagem do Wikimedia Commons (da Phasmatinox / Allefant , usada sob a licença CC-By-SA 3.0 ):

        Projeção isométrica de um objeto estendido dividido em cubos

A cômoda da foto ocupa dois ladrilhos, e eu desenhei os limites desses ladrilhos (os hexágonos vermelhos) em cima. As partes da imagem que ficam dentro de cada hexágono devem ser atribuídas ao bloco correspondente; a parte em que os hexágonos se sobrepõem pode ser atribuída a um bloco (ou mesmo a ambos, se você preferir), pois a escolha não afetará o resultado final.

Observe que você pode precisar elaborar esse algoritmo simples se puder ter vários objetos em um bloco, paredes / pisos entre blocos ou objetos (como pessoas) se movendo suavemente entre blocos. Paredes e pisos são bem simples de manusear: eles podem ser desenhados a qualquer momento após o conteúdo do bloco em que estão na frente (do ponto de vista da câmera) e antes do bloco em que estão atrás. Essa também é uma regra prática para objetos que se movem entre blocos; trate-os como faria com uma parede entre esses ladrilhos.

Quanto a vários objetos em um ladrilho, às vezes esses são bem simples: por exemplo, se você tivesse um livro em cima do peito na imagem, ele obviamente deveria ser desenhado após a superfície em que se encontra. No entanto, as coisas podem ficar mais complicadas se, por exemplo, você tiver objetos em que as pessoas possam se sentar. Por exemplo, se uma pessoa estava sentada em um banco, de costas para a câmera, o corpo da pessoa deveria ser puxado atrás do banco, mas suas pernas (que estão atrás do banco da câmera) precisam ser puxadas antes dele. Uma solução, nesse caso, seria dividir as pernas de uma pessoa sentada em um componente separado com sua própria posição (no ladrilho adjacente ou entre os ladrilhos).

Ilmari Karonen
fonte
1

Isso pode ajudá-lo a particionar seus objetos por tipo ou altitude. Por exemplo, a paisagem (pisos, paredes) deve ser desenhada antes dos objetos (camas). Além disso, devido à perspectiva isométrica, os ladrilhos de menor altitude devem ser desenhados antes dos de maior altitude.

Além disso, se você optar pela numeração de índices (ordenação Z, na verdade), recomendo usar espaços entre os números - não faça o chão 1e a cama 2. Use algo como andares = 10e camas = 20ou 100qualquer outra coisa, para que você possa "inserir" coisas no meio sem aumentar o dominó em tudo.

ashes999
fonte
Eu pretendo fazer o que você sugere no primeiro parágrafo. O problema que estou tendo é que os objetos de um tipo semelhante estão sobrepostos incorretamente. por exemplo, minha cama se sobrepõe à mesa de cabeceira. Eu estava sugerindo que eu desse a cada instância de uma imagem um número diferente, não dando a todas as camas o número 20, por exemplo?
Roger Smith
Depende. E se você tiver duas camas próximas uma da outra? Uma maneira de as pessoas contornarem isso é adicionar objetos na ordem em que devem ser desenhados, mas não sei se isso irá ajudá-lo.
precisa saber é o seguinte
11
Se duas camas estiverem próximas uma da outra, a cama com o maior valor de y deve ser desenhada acima da outra. Se eles forem iguais coordenada y, então aquele com o maior valor de x (assumindo topo do mapa é (0,0).
Roger Smith