2011-02-23 25 views
5

Así que estoy jugando con OpenGL y tratando de encontrar la manera de dibujar algunas formas divertidas.OpenGL Tube Along a Path

Ahora mismo, estoy trabajando en un tubo. Puedo dibujar un tubo recto muy bien con:

void tube(GLfloat radius, GLfloat segment_length) { 
    glPolygonMode(GL_BACK, GL_NONE); 
    glPolygonMode(GL_FRONT, GL_FILL); 

    glPushMatrix(); { 
     GLfloat z1 = 0.0; 
     GLfloat z2 = segment_length; 

     GLfloat y_offset = 0.0; 
     GLfloat y_change = 0.00; 

     int i = 0; 
     int j = 0; 
     for (j = 0; j < 20; j++) { 
      glPushMatrix(); { 
       glBegin(GL_TRIANGLE_STRIP); { 
        for (i = 360; i >= 0; i--) { 
         GLfloat theta = i * pi/180; 
         GLfloat x = radius * cos(theta); 
         GLfloat y = radius * sin(theta) + y_offset; 

         glVertex3f(x, y, z1); 
         glVertex3f(x, y, z2); 
        } 
       } glEnd(); 
      } glPopMatrix(); 

      // attach the front of the next segment to the back of the previous 
      z1 = z2; 
      z2 += segment_length; 

      // make some other adjustments 
      y_offset += y_change; 
     } 
    } glPopMatrix(); 
} 

Sin embargo, no he encontrado la manera de hacer que el tubo sigue ningún camino predefinido como una espiral, o incluso una simple línea. Si cambia y_change a algo así como 0.01, dibujará cada offset de segmento de tubo un 0.01 adicional en la dirección y. Eso es genial, pero ¿cómo puedo hacer que cada segmento se dirija en esa dirección? En otras palabras, en este momento, cada segmento se dibuja de modo que todos se dirigen en la misma dirección, y la dirección no es la dirección del tubo (ya que con y_change = 0.01, la dirección es ligeramente "arriba").

No estoy seguro de cómo proceder. He jugado con vectores obteniendo el vector entre el segmento anterior y el actual, pero no estoy seguro de qué hacer con eso más allá de eso.

+1

¿Ha mirado (para un ejemplo) Ejemplo de toro del Libro Rojo? http://www.opengl.org/resources/code/samples/redbook/torus.c –

Respuesta

17

La idea se llama extrusión controlada por trayecto, es decir, tiene una forma n dimensional básica y la extruye a lo largo de una curva n + 1 dimensional. Puedo leer tu cara: "Huh, ¿qué está diciendo?"

Así que aquí hay un esquema grueso. Primero necesita una función que asigne un valor, generalmente llamado t, a una curva continua y suave en el espacio. Por ejemplo un tornillo:

path(t): R → R³, t ↦ (a·sin(k·t), b·cos(k·t), c·t) 

La idea es, para encontrar una base localizada de coordenadas para definir sus posiciones vértices en relación a esa ruta - que tiene sentido, que una de las coordenadas está alineado en paralelo a la ruta, así que quieres encontrar que es tangente. Esto se hace mediante la búsqueda de su gradiente:

tangent(t): R → R³, t ↦ (k·a·cos(k·t), -k·b·sin(k·t), c) = d/dt path(t) 

Así que este es el vector base local que está apuntando a lo largo de la curva, con el origen del sistema de coordenadas local en el punto t de la curva.

Pero necesitamos otros dos vectores para formar una base 3d completa. Por lo general, es una buena opción para tener el segundo punto base perpendicular a la curvatura, que se obtiene mediante la búsqueda de la curvatura de la tangente:

normal(t): R → R³, t ↦ (-k²·a·sin(k·t), -k²·b·cos(k·t), 0) = d/dt tangent(t) = d²/dt² path(t) 

Esto se conoce como la normal.

Se puede obtener el vector base en tercera dimensión, tomando el producto cruzado de normal y tangente, produciendo el binormal. Dejaré que lo resuelvas como ejercicio.

Ahora para extruir una forma a lo largo de la curva, debe dividir la ruta en segmentos, simplemente iterando t en un rango elegido, que le da el origen local. Los puntos de su forma extruida son relativos a esta ruta de origen (t). Digamos que su forma se compone de los puntos P_n en el plano x-y a continuación:

for t in [k..l]: 
    for p in P_n: 
     yield_vertex(path(t).x + binormal(t).x * p.x, 
         path(t).y + normal(t).y * p.y, 
         path(t).z) 

lo dejo a usted, encontrar la manera de adaptar este a OpenGL, después de todo, usted debe aprender algo pensando en él. Si no puede resolverlo hasta mañana, con mucho gusto le daré la solución, pero generalmente es más divertido averiguar las cosas por su cuenta.

+1

+1: Excelente respuesta. Si está interesado en una función lineal por partes, puede encontrar la tangente como el promedio de v (n) (el vector desde el último punto hasta este) yv (n + 1) (el vector de este punto a la próxima). –

+0

impresionante, gracias por esta respuesta. Voy a pasar un tiempo trabajando en esto. Te dejaré saber qué progreso hago (aunque la escuela y el trabajo pueden consumir parte de mi tiempo de recreación que reservé para esto). – gregghz

+0

sí, me temo que mis habilidades matemáticas no están a la altura de esto (parte del problema puede ser que no entiendo completamente tu notación). Parece que no puedo traducir eso a OpenGL, parece que no importa lo que haga, los segmentos del tubo siempre miran en una dirección. – gregghz