2012-02-16 23 views
8

que tiene un juego simple que utiliza una representación 3D cuadrícula, algo así como:juego 3D Geometría

Blocks grid[10][10][10]; 

La persona en el juego está representado por un punto y un vector de vista:

double x,y,z, dx,dy,dz; 

trazo la cuadrícula con 3 bucles for anidados:

for(...) for(...) for(...) 
    draw(grid[i][j][k]); 

el problema obvio de esto es cuando el tamaño de la red crece dentro del hun dreds, fps caen dramáticamente. Con un poco de intuición, me di cuenta que:

  • bloques que estaban ocultos por otros bloques en la red no tienen que ser prestados
  • Los bloques que no estaban dentro del campo de visión de la persona también no necesitan ser prestados (es decir. bloques que estaban detrás de la persona)

Mi pregunta es, dado un grid[][][], un vector vista dx,dy,dz de la persona x,y,z, y, ¿cómo podría averiguar qué necesitan bloques a ser prestados y que don' t?

+1

Este es un tema bastante amplio, cubierto bien en [Determinación de superficie oculta] (http : //en.wikipedia.org/wiki/Hidden_surface_determination). –

+4

Si usa OpenGL, o cualquier otra biblioteca 3D, lo hace _culling_ automáticamente en el renderizado final. – toto2

+0

Entonces, si uso OpenGL, ¿entonces agregar la optimización geométrica no afectará el rendimiento general? –

Respuesta

7

Analicé el uso de JMonkeyEngine, un motor de juegos en 3D, hace un tiempo y estudié algunas de las técnicas que emplean. Por lo que recuerdo, utilizan algo llamado sacrificio. Construyen una estructura de árbol de todo lo que existe en el "mundo". La idea es que tienes un subconjunto de este árbol que representa los objetos visibles en un momento dado. En otras palabras, estas son las cosas que deben presentarse. Entonces, di por ejemplo que tengo una habitación con objetos en la habitación. La habitación está en el árbol y los objetos en la habitación son hijos del árbol. Si estoy fuera de la habitación, podo (elimino) esta rama del árbol, lo que significa que no la renderizo. La razón por la que esto funciona tan bien es que no tengo que evaluar TODOS los objetos del mundo para ver si se debe procesar, sino que elimino partes enteras del mundo que sé que no deberían procesarse.

Mejor aún, cuando entro en la sala, recorto todo el resto del mundo del árbol y luego solo renderizo la habitación y todos sus descendientes.

Creo que muchas de las decisiones de diseño que hizo el equipo de JMonkeyEngine se basaron en las cosas del libro de David Eberly, 3D Game Engine Design. No conozco los detalles técnicos de cómo implementar un enfoque como este, pero apuesto a que este libro sería un excelente punto de partida para usted.

Aquí es una interesante article en algunos diferentes algoritmos de sacrificio:

  • Ver Frustum Culling
  • Volver cara Desvieje
  • oclusión basada en células sacrificio
  • PVS basada en arbitraria la oclusión de la geometría sacrificio
  • Otros
+0

"En la versión ingenua de este algoritmo, cada objeto en el mundo se prueba en comparación con los seis planos". ¿Cómo voy a implementar algo como esto? No estoy particularmente interesado en estructuras de octree complejas, etc. –

+3

Si no está interesado en implementar lo que se considera un enfoque estándar para el problema que ha explicado en su pregunta, entonces es posible que desee ajustar sus esfuerzos. En lugar de tratar de hacer todo esto usted mismo, use una biblioteca. Hay toneladas en C++ y sé que uno de los mejores de Java es JMonkeyEngine (que he vinculado anteriormente). – jbranchaud

1

Primero necesita una estructura de división espacial, si está usando tamaños de bloque uniformes, probablemente la estructura más efectiva será octree. Luego, tendrá que escribir un algoritmo que pueda calcular si un cuadro está en un lado particular de (o se cruza) un plano.Una vez que tenga eso, puede averiguar qué nodos de la hoja del octárbol están dentro de los seis lados de su vista trunco ​​- eso es ver descarte. También usando el octree puedes determinar qué bloques ocluyen a otros (a veces llamado enmascaramiento de frustum), pero obtén la primera parte que funcione primero.

1

Suena como si estuvieras buscando algo de tipo minecraft-y. Eche un vistazo a this android minecraft level renderer. Los puntos a tener en cuenta son:

  • Sólo hay que dibujar las caras de los bloques que se comparten con bloques transparentes. por ejemplo, no te molestes en dibujar caras entre dos bloques opacos: el jugador nunca los verá.
  • Probablemente quiera agrupar la geometría de bloque visible en bloques (y pegarlo en una VBO) y determinar la visibilidad en cada porción. Encontrar exactamente qué bloques de se pueden ver probablemente llevará más tiempo que simplemente arrojar el VBO en el gpu y aceptar el sobregiro.
  • Un relleno de inundación funciona bastante bien para determinar qué bloques son visibles: limite el relleno usando la vista troncocónica, vea la dirección (si está mirando en la dirección + vex, no inunde en la dirección -ve) , y análisis simples de datos de chunklet (por ejemplo: si una cara entera de un bloque es opaca, no se inunde en esa cara)
+0

¡Gracias, el relleno de inundación funciona increíblemente bien! –

Cuestiones relacionadas