quads - polygon opengl c++
Drawing Sphere en OpenGL sin usar gluSphere()? (8)
Además, explicaré una forma popular de generar una esfera usando latitud y longitud (de otra manera, icospheres , ya se explicó en la respuesta más popular en el momento de escribir esto).
Una esfera se puede expresar con la siguiente ecuación paramétrica:
F ( u , v ) = [cos (u) * sin (v) * r, cos (v) * r, sin (u) * sin (v) * r]
Dónde:
- r es el radio;
- u es la longitud, que va 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 ajusta).
El siguiente pseudocódigo genera una malla triangular al evaluar una función paramétrica a intervalos regulares (esto funciona para cualquier función de superficie paramétrica, no solo para 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 la 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)
}
}
¿Hay algún tutorial que explique cómo puedo dibujar una esfera en OpenGL sin tener que usar gluSphere()
?
Muchos de los tutoriales en 3D para OpenGL son solo en cubos. He buscado, pero la mayoría de las soluciones para dibujar una esfera son para 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 ese enlace. Pero, de nuevo, no entiendo cómo se dibujan las esferas con el código. Quiero poder visualizar para poder modificar la esfera si es necesario.
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). Como la solución propuesta por @Kevin no proporciona esta característica, pensé que podría agregar un enfoque que sí lo haga.
Una buena forma de generar un poliedro de cara N donde todos los vértices se encuentran en la misma esfera y todas sus caras tienen una superficie / área similar está comenzando con un icosaedro y subdividiendo y normalizando iterativamente sus caras triangulares (como se sugiere en la respuesta aceptada ) Los dodecaedros, por ejemplo, en realidad son 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 http://www.glprogramming.com/red/chapter02.html#name8 .
Sé que esto está un poco fuera de tema, pero creo que puede ayudar si alguien llega aquí buscando este caso específico.
Consulte el libro rojo de OpenGL: http://www.glprogramming.com/red/chapter02.html#name8 Soluciona el problema por subdivisión de polígono.
El código en la muestra se explica rápidamente. Debería examinar la función void drawSphere(double r, int lats, int longs)
. Los parámetros lat
definen cuántas líneas horizontales quieres tener en tu esfera y cuántas líneas verticales. r
es el radio de tu esfera.
Ahora hay una doble iteración sobre lat
/ lon
y las coordenadas de los vértices 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 dos vértices que forman un quad 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 resolverlo fácilmente.
Mi ejemplo de cómo usar "tira de triángulo" 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 ingresado (glVertex3f) es como sigue la ecuación paramétrica y el segundo se desplaza en un solo paso de ángulo alfa (del próximo paralelo).
Si quisieras ser astuto como un zorro, podrías medio pulgar el código de GLU. Consulte el código fuente de MesaGL (http://cgit.freedesktop.org/mesa/mesa/).
Una forma de hacerlo es comenzar con un sólido platónico con lados triangulares: un octahedron , por ejemplo. Luego, toma cada triángulo y divídelo recursivamente en triángulos más pequeños, de esta forma:
Una vez que tienes una cantidad suficiente de puntos, normalizas sus vectores para que estén todos a una distancia constante del centro del sólido. Esto hace que los lados se abomben en una forma que se asemeja a una esfera, con una suavidad creciente a medida que aumenta la cantidad de puntos.
La normalización aquí significa mover un punto para que su ángulo en relación con otro punto sea el mismo, pero la distancia entre ellos es diferente. Aquí hay un ejemplo bidimensional.
A y B están separados por 6 unidades. Pero supongamos que queremos encontrar un punto en la línea AB que esté a 12 unidades de distancia de A.
Podemos decir que C es la forma normalizada de B con respecto a A, con la distancia 12. Podemos obtener C con un código como este:
#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 se encontrarán en el arco de un círculo con el centro A y el radio R.
Aquí, los puntos negros comienzan en una línea y se "abultan" formando un arco.
Este proceso puede extenderse a tres dimensiones, en cuyo caso se obtiene una esfera en lugar de un círculo. Solo agrega un componente dz a la función de normalización.
Si miras la esfera en Epcot , puedes ver cómo funciona esta técnica. es un dodecaedro con caras abultadas para que se vea más redondo.
Una forma es hacer un quad que mire hacia la cámara y escribir un vértice y un sombreador de fragmentos que represente algo que se parece a una esfera. Puede usar ecuaciones para un círculo / esfera que puede 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 más como una elipse. Podrías resolver las ecuaciones para esto y ponerlas en el sombreado del fragmento. Entonces el sombreado de la luz debe cambiar a medida que el jugador se mueve, si realmente tiene un jugador moviéndose en el espacio 3D alrededor de la esfera.
¿Alguien puede comentar si lo han intentado o si sería demasiado caro para ser práctico?