¿Dibujar una esfera en OpenGL sin usar gluSphere()?


¿Hay algún tutorial que explique cómo puedo dibujar una esfera en OpenGL sin tener que usar gluSphere()?

Muchos de los tutoriales 3D para OpenGL son solo sobre cubos. He buscado pero la mayoría de las soluciones para dibujar una esfera son usar gluSphere(). También hay un sitio que tiene el código para dibujar una esfera en este sitio pero no explica las matemáticas detrás de dibujar la esfera. También tengo otras versiones de cómo dibujar la esfera en polígono en lugar de quads en que enlace. Pero de nuevo, no entiendo cómo se dibujan las esferas con el código. Quiero ser capaz de visualizar para que pueda modificar la esfera si lo necesito.

Author: user1118321, 2011-10-07

8 answers

Una manera de hacerlo es comenzar con un sólido platónico con lados triangulares - un octaedro, por ejemplo. Luego, toma cada triángulo y divídelo recursivamente en triángulos más pequeños, así:

triángulos dibujados recursivamente

Una vez que se tiene una cantidad suficiente de puntos, se normalizan sus vectores para que todos estén a una distancia constante desde el centro del sólido. Esto hace que los lados sobresalgan en una forma que se asemeja a una esfera, con una suavidad creciente a medida que aumenta el número de puntos.

Normalización aquí significa mover un punto de modo que su ángulo en relación con otro punto es el mismo, pero la distancia entre ellos es diferente. Aquí hay un ejemplo bidimensional.

introduzca la descripción de la imagen aquí

A y B están separadas por 6 unidades. Pero supongamos que queremos encontrar un punto en la línea AB que está a 12 unidades de A.

introduzca la descripción de la imagen aquí

Podemos decir que C es la forma normalizada de B con respecto a A, con distancia 12. Podemos obtener C con código como esto:

#returns a point collinear to A and B, a given distance away from A. 
function normalize(a, b, length):
    #get the distance between a and b along the x and y axes
    dx = b.x - a.x
    dy = b.y - a.y
    #right now, sqrt(dx^2 + dy^2) = distance(a,b).
    #we want to modify them so that sqrt(dx^2 + dy^2) = the given length.
    dx = dx * length / distance(a,b)
    dy = dy * length / distance(a,b)
    point c =  new point
    c.x = a.x + dx
    c.y = a.y + dy
    return c

Si hacemos este proceso de normalización en muchos puntos, todos con respecto al mismo punto A y con la misma distancia R, entonces los puntos normalizados estarán todos en el arco de un círculo con centro A y radio R.

segmento de línea abultada

Aquí, los puntos negros comienzan en una línea y "sobresalen" en un arco.

Este proceso se puede extender en tres dimensiones, en cuyo caso se obtiene una esfera en lugar de un círculo. Simplemente agregue un componente dz a normalizar función.

polígonos normalizados

octaedro abultado de nivel 1octaedro abultado de nivel 3

Si nos fijamos en la esfera en Epcot, se puede ver una especie de esta técnica en el trabajo. es un dodecaedro con caras abultadas para que parezca más redondo.

 239
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-28 18:22:48

Explicaré más a fondo una forma popular de generar una esfera usando latitud y longitud (otro camino, icosferas , ya se explicó en la respuesta más popular en el momento de este escrito.)

Una esfera se puede expresar mediante la siguiente ecuación paramétrica:

F(u, v) = [ cos(u)*sin(v)*r, cos(v)*r, el pecado(u)*sin(v)*r ]

Donde:

  • r es el radio;
  • u es la longitud, que van de 0 a 2π; y
  • v es la latitud, que va de 0 a π.

Generar la esfera implica evaluar la función paramétrica a intervalos fijos.

Por ejemplo, para generar 16 líneas de longitud, habrá 17 líneas de cuadrícula a lo largo del eje u, con un paso de π/8 (2π / 16) (la línea 17 se envuelve).

El siguiente pseudocódigo genera una malla triangular mediante la evaluación de una función paramétrica a intervalos regulares (esto funciona para cualquier función de superficie paramétrica, no solo esferas).

En el pseudocódigo siguiente, UResolution es el número de puntos de la cuadrícula a lo largo del eje U (aquí, líneas de longitud), y VResolution es el número de puntos de cuadrícula a lo largo del eje V (aquí, líneas de latitud)

var startU=0
var startV=0
var endU=PI*2
var endV=PI
var stepU=(endU-startU)/UResolution // step size between U-points on the grid
var stepV=(endV-startV)/VResolution // step size between V-points on the grid
for(var i=0;i<UResolution;i++){ // U-points
 for(var j=0;j<VResolution;j++){ // V-points
 var u=i*stepU+startU
 var v=j*stepV+startV
 var un=(i+1==UResolution) ? EndU : (i+1)*stepU+startU
 var vn=(j+1==VResolution) ? EndV : (j+1)*stepV+startV
 // Find the four points of the grid
 // square by evaluating the parametric
 // surface function
 var p0=F(u, v)
 var p1=F(u, vn)
 var p2=F(un, v)
 var p3=F(un, vn)
 // NOTE: For spheres, the normal is just the normalized
 // version of each vertex point; this generally won't be the case for
 // other parametric surfaces.
 // Output the first triangle of this grid square
 triangle(p0, p2, p1)
 // Output the other triangle of this grid square
 triangle(p3, p1, p2)
 }
}
 20
Author: Peter O.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 16:08:52

El código de la muestra se explica rápidamente. Usted debe mirar en la función void drawSphere(double r, int lats, int longs). Los parámetros lat definen cuántas líneas horizontales desea tener en su esfera y lon cuántas líneas verticales. r es el radio de tu esfera.

Ahora hay una doble iteración sobre lat/lon y las coordenadas del vértice se calculan, usando trigonometría simple.

Los vértices calculados ahora se envían a su GPU usando glVertex...() como GL_QUAD_STRIP, lo que significa que está enviando cada uno dos vértices que forman un cuadrante con los dos enviados previamente.

Todo lo que tienes que entender ahora es cómo funcionan las funciones de trigonometría, pero supongo que puedes averiguarlo fácilmente.

 2
Author: Constantinius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-07 12:42:42

Si quisieras ser astuto como un zorro podrías medir medio centímetro el código de GLU. Echa un vistazo al código fuente de MesaGL (http://cgit.freedesktop.org/mesa/mesa/).

 1
Author: blockchaindev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-07 12:44:06

Ver el libro rojo de OpenGL: http://www.glprogramming.com/red/chapter02.html#name8 Resuelve el problema por subdivisión de polígonos.

 1
Author: Walter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-23 20:12:21

Aunque la respuesta aceptada resuelve la pregunta, hay un pequeño error al final. Los dodecaedros son (o podrían ser) poliedros regulares donde todas las caras tienen la misma área. Ese parece ser el caso del Epcot (que, por cierto, no es un dodecaedro en absoluto). Dado que la solución propuesta por @ Kevin no proporciona esta característica, pensé que podría agregar un enfoque que sí lo hace.

Una buena manera de generar un poliedro de N caras donde se encuentran todos los vértices en la misma esfera y todas sus caras tienen área/superficie similar está comenzando con un icosaedro y la iterativamente subdividiendo y normalizando sus caras triangulares (como se sugiere en la respuesta aceptada). Dodecaedros, por ejemplo, son en realidad icosaedros truncados .

Los icosaedros regulares tienen 20 caras (12 vértices) y se pueden construir fácilmente a partir de 3 rectángulos dorados; es solo cuestión de tener esto como punto de partida en lugar de un octaedro. Puede encontrar un ejemplo aquí.

Sé que esto es un poco fuera de tema, pero creo que puede ayudar si alguien llega aquí en busca de este caso específico.

 1
Author: Carles Araguz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-22 10:21:59

Mi ejemplo de cómo usar 'triangle strip' para dibujar una esfera "polar", consiste en dibujar puntos en pares:

const float PI = 3.141592f;
GLfloat x, y, z, alpha, beta; // Storage for coordinates and angles        
GLfloat radius = 60.0f;
int gradation = 20;

for (alpha = 0.0; alpha < GL_PI; alpha += PI/gradation)
{        
    glBegin(GL_TRIANGLE_STRIP);
    for (beta = 0.0; beta < 2.01*GL_PI; beta += PI/gradation)            
    {            
        x = radius*cos(beta)*sin(alpha);
        y = radius*sin(beta)*sin(alpha);
        z = radius*cos(alpha);
        glVertex3f(x, y, z);
        x = radius*cos(beta)*sin(alpha + PI/gradation);
        y = radius*sin(beta)*sin(alpha + PI/gradation);
        z = radius*cos(alpha + PI/gradation);            
        glVertex3f(x, y, z);            
    }        
    glEnd();
}

El primer punto introducido (glVertex3f) es como sigue la ecuación paramétrica y el segundo se desplaza por un solo paso del ángulo alfa (desde el siguiente paralelo).

 0
Author: bloody,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-17 13:10:18

Una forma es hacer un quad que mire a la cámara y escribir un sombreador de vértices y fragmentos que renderice algo que se parezca a una esfera. Puedes usar ecuaciones para un círculo / esfera que puedes encontrar en Internet.

Una cosa buena es que la silueta de una esfera se ve igual desde cualquier ángulo. Sin embargo, si la esfera no está en el centro de una vista en perspectiva, entonces parecería quizás más como una elipse. Usted podría resolver las ecuaciones para esto y ponerlos en el sombreado de fragmentos. Luego, el sombreado de la luz debe cambiar a medida que el jugador se mueve, si realmente tiene un jugador que se mueve en el espacio 3D alrededor de la esfera.

¿Puede alguien comentar si ha probado esto o si sería demasiado caro para ser práctico?

 0
Author: Steven2163712,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-22 02:28:13