De acordo com a página da Wikipedia sobre voxels, "[...] a posição de um voxel é inferida com base em sua posição em relação a outros voxels (ou seja, sua posição na estrutura de dados que compõe uma única imagem volumétrica)".
Como se deve implementar essa estrutura de dados? Eu estava pensando em uma octree, mas me pergunto se há algo mais sobre o qual nunca ouvi falar.
data-structure
terrain
voxels
pwny
fonte
fonte
Respostas:
Primeiro. Vamos escrever o que sabemos sobre cada voxel:
Armazenamento geral
A maneira geral é simplesmente esta:
Observe que esse trigêmeo (x, y, z) identifica cada voxel de forma única, uma vez que o voxel é um ponto no espaço e não há como dois pontos ocuparem um lugar (acredito que estamos falando de dados estáticos de voxel).
Deve ser bom para dados simples. Mas não é de forma alguma uma estrutura de dados rápida.
A renderização é AFAIK feita pelo algoritmo scanline. O artigo de Tom's Hardware sobre voxels possui uma imagem do algoritmo scanline .
Pesquisa rápida
Se a pesquisa rápida for necessária, a estrutura de dados mais rápida para a pesquisa é o hash (também conhecido como array, mapa ...). Então você tem que fazer hash com isso. Então, ingenuamente, queremos a maneira mais rápida de obter um elemento arbitrário:
Isso tem O (1) para procurar voxel pelas coordenadas x, y, z.
O problema é que seus requisitos de espaço são O (D ^ 3), onde D é o intervalo de cada número x, ye z (esqueça o número real, pois se fossem caracteres Chars, com intervalo de 256 valores, haveria 256 ^ 3 = 2 ^ 24 == 16 777 216 elementos na matriz).
Mas isso depende do que você quer fazer com voxels. Se a renderização é o que você deseja, provavelmente é essa matriz o que você deseja. Mas o problema de armazenamento ainda permanece ...
Se o armazenamento é o problema
Um método é usar a compactação RLE na matriz. Imagine uma fatia de voxels (conjunto de voxels, em que voxels têm um valor constante de coordenada ... como um plano em que z = 13, por exemplo). Essa fatia de voxels pareceria um desenho simples no MSPaint . O modelo Voxel, eu diria, geralmente ocupa fração de todos os lugares possíveis (espaço D ^ 3 de todos os possíveis voxels). Eu acredito que "pegar um par de trigêmeos de coordenadas e comprimir o eixo restante" faria o truque (por exemplo, pegue [x] [y] e, para cada elemento, comprima todos os voxels no eixo z em x, y .. deve haver de 0 a poucos elementos, o RLE faria bem aqui):
Outro método para resolver o problema de armazenamento seria, em vez de matriz, usando a estrutura de dados em árvore:
Se os voxels são um mapa de altura simplista, você pode armazenar exatamente isso. Ou você pode armazenar parâmetros para funcionar, o que gera o mapa de altura, também conhecido como procedimento.
E, claro, você pode combinar todas as abordagens possíveis. Mas não exagere, a menos que você teste se seu código funciona e meça REALMENTE mais rápido (por isso vale a pena a otimização).
TL; DR
Além de Octrees, é a compactação RLE com voxels, google "voxlap", "ken silverman" ...
Recursos
Há uma lista de recursos e discussão sobre como fazer renderizador voxel rápido, inclui papéis e código fonte .
fonte
Existem dois aspectos diferentes da estrutura de dados sobre os quais eles podem estar falando.
Estruturas de matriz
Ao fazer referência a um elemento de uma matriz de qualquer número de dimensões, considere que a própria matriz, depois de passar os índices (por exemplo,
myArray[4][6][15]
), sabe o que está nesse local. Se o que está nesse local é um voxel, esse voxel não precisa registrar adicionalmente suas próprias coordenadas x, ye z - a matriz que contém o voxel especifica sua localização mundial implicitamente com base em sua localização indexada à matriz.A razão disso é que a aritmética do ponteiro usada para esse tipo de acesso à matriz é inerentemente rápida e, de um modo geral, fornece a base para a maioria das matrizes rápidas (geralmente chamadas de "nativas") encontradas nos idiomas. A desvantagem dessas matrizes é que elas devem ter elementos de tamanho igual em bytes, para que a referida aritmética do ponteiro seja aplicável.
Octrees
(Observo este segundo, porque é menos provável que isso se refira à wikipedia e as implementações de voxel não exigem o uso de octrees, embora quase todas as modernas usem octrees.)
O nó raiz de um octree é um cubo único e não dividido. Vamos criar um exemplo. Digamos que a raiz do seu octree, o centro do cubo, esteja no
{0, 0, 0}
espaço 3D. Depois que você começa a colocar objetos nesse espaço (leia: mais de um objeto), é hora de subdividir ainda mais a octree. É aqui que você se divide em 8 ( outubro ), cortando-o usando 3 planos, sendo esses planos os planos xy, xz e yz. Seu cubo original agora contém exatamente 8 cubos menores. Cada um desses subnós é posicionado como um deslocamento do cubo pai central . Ou seja, que, por exemplo, o cubo localizado no octante xyz positivo teria um deslocamento do centro do cubo pai / contendo exatamente{root.width / 4, root.height / 4, root.depth / 4}
. Em vez de especificar uma posição absoluta para cada subnó, faz mais sentido lógico considerar o nó pai como a origem do espaço do seu filho. É assim que os gráficos de cena funcionam.É simples o suficiente para ver isso em um desenho 2D, onde você desenha um quadrado e subdividi-lo em 4 regiões iguais. Se, como nosso nó raiz octree, o centro do quadrado pai fosse considerado
{0, 0}
, então os 4 centros dos quadrados filhos seriam{root.width / 4, root.height / 4}
,{-root.width / 4, root.height / 4}
,{root.width / 4, -root.height / 4}
,{-root.width / 4, -root.height / 4}
... Em relação aos pais - o mesmo princípio que em 3D.
fonte
Você pode usar o RLE. Mas você pode usar o SVO (Sparse Voxel Octree), o id Tech 6 usa o SVO. Um SVO é uma técnica de renderização de gráficos de computador em 3D usando uma transmissão de raios ou, às vezes, uma abordagem de rastreamento de raios em uma representação de dados octree.
A técnica varia um pouco, mas geralmente depende da geração e processamento do casco de pontos (voxels esparsos) que são visíveis ou podem ser visíveis, dada a resolução e o tamanho da tela.
Use raycasting, porque é mais rápido.
fonte
Geralmente, você pode evitar uma estrutura de dados 3D para terrenos. Você pode usar um mapa de altura . Isso pode ser voxelizado de maneira muito barata e eficiente em tempo de execução. Geralmente vale a pena (na minha experiência) rastrear a altura mínima que você precisa renderizar em cada coluna e, às vezes, também os ângulos start-stop-top para que você possa selecionar também as colunas da face posterior.
Aqui está um que eu fiz há muito tempo: http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash
Se o terreno possui um pequeno número de saliências, cavernas ou outros recursos que não podem ser representados por um mapa de altura, você pode fazer furos no mapa de altura e ter uma representação alternativa, por exemplo, objetos voxel 3D verdadeiros que preenchem apenas os locais localizados onde as despesas de execução é garantido.
Representações esparsas de voxel valem a pena quando você tem grandes mundos verdadeiros de voxel. John Carmack tem falado com eles nos últimos anos ...
fonte