OpenGL es una poderosa herramienta de programación 3D que se utiliza para dibujar escenas tridimensionales complejas a partir de primitivas simples. ¡Este artículo te enseñará cómo dibujar un cubo simple que puedes girar para verlo en tres dimensiones!
Para este proyecto, necesitará un editor de código y algunos conocimientos de programación en C.
Pasos
Parte 1 de 3: Configuración inicial
Paso 1. Instale OpenGL Para comenzar, siga estos pasos para instalar OpenGL en su sistema
Si ya tiene OpenGL, así como un compilador C compatible instalado, puede omitir este paso y pasar al siguiente.
Paso 2. Cree el documento
Cree un nuevo archivo en su editor de código favorito y guárdelo como mycube.c
Paso 3. Agregue #includes
Estas son las inclusiones básicas que necesitará para su programa. Es importante darse cuenta de que en realidad se requieren diferentes inclusiones para los diferentes sistemas operativos. Asegúrese de incluir todos estos para asegurarse de que su programa sea versátil y pueda ejecutarse para cualquier usuario.
// Incluye #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif
Paso 4. Agregue prototipos de funciones y variables globales
El siguiente paso es declarar algunos prototipos de funciones.
// Prototipos de funciones void display (); void specialKeys (); // Variables globales double rotate_y = 0; doble rotate_x = 0;
Paso 5. Configure la función principal ()
int main (int argc, char * argv ) {// Inicializa GLUT y procesa los parámetros de usuario glutInit (& argc, argv); // Solicitar una ventana de color verdadero con doble búfer con Z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
Paso 6. Cree la ventana
El siguiente paso es crea la ventana dentro del cual dibujarás el cubo. En este tutorial, la ventana se llama "Awesome Cube".
// Crear ventana glutCreateWindow ("Awesome Cube");
Paso 7. Habilite la prueba de profundidad
OpenGL es un lenguaje estricto en el sentido de que no asume que se habiliten funciones especiales. Para que su programa se muestre correctamente en 3 dimensiones usando el búfer Z que miró anteriormente, necesita habilitar prueba de profundidad. A medida que continúe explorando OpenGL, descubrirá muchas funciones que deberá habilitar, incluidas iluminación, texturas, eliminación selectiva y mucho más.
// Habilita la prueba de profundidad del búfer Z glEnable (GL_DEPTH_TEST);
Paso 8. Agregue funciones de devolución de llamada
Estas son las funciones de devolución de llamada para las que escribió los prototipos anteriormente. Cada vez que pase por el bucle principal, se llamarán estas funciones. La función de visualización vuelve a dibujar la escena en función de los cambios realizados en las variables desde la llamada anterior. La función specialKeys nos permite interactuar con el programa.
// Funciones de devolución de llamada glutDisplayFunc (display); glutSpecialFunc (teclas especiales);
Paso 9. Inicie MainLoop
Esto recordará la función principal hasta que cierre el programa para permitir las animaciones y la interacción del usuario.
// Pasar el control a GLUT para eventos glutMainLoop (); // Regresar al SO return 0; }
Parte 2 de 3: La función display ()
Paso 1. Comprenda el propósito de esta función
Todo el trabajo de dibujar tu cubo se realizará en esta función. La idea general detrás de su cubo es dibujar los seis lados individualmente y colocarlos en la posición adecuada.
Conceptualmente, cada lado se dibujará definiendo las cuatro esquinas y dejando que OpenGL conecte las líneas y lo rellene con un color que usted defina. A continuación se muestran los pasos para hacer esto
Paso 2. Agregue glClear ()
El primer paso que debe realizar en esta función es borrar el color y el búfer Z. Sin estos pasos, los dibujos antiguos pueden seguir siendo visibles debajo de los nuevos dibujos y los objetos dibujados no estarían en la ubicación correcta en la pantalla.
void display () {// Limpiar pantalla y Z-buffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Paso 3. Agregue glBegin () y glEnd ()
OpenGL define los objetos como combinaciones de diferentes polígonos. Utilizando el glBegin () comando, efectivamente dejas un lápiz que dibujará una forma. Para levantar el lápiz y comenzar una nueva forma, debe usar el glEnd () mando. En este tutorial, usará GL_POLYGON para dibujar cada lado del cubo, pero es posible usar otras opciones de parámetros como GL_LINE, GL_QUAD o GL_TRIANGLE para crear otras formas.
- Aquí comenzará con el frente de su cubo. Luego agregará color a los 6 lados.
// Lado multicolor - FRONT glBegin (GL_POLYGON); // Los vértices se agregarán en el siguiente paso glEnd ();
Paso 4. Agregue glVertex3f ()
Una vez que haya indicado que desea comenzar su polígono, debe definir los vértices del objeto. glVertex tiene múltiples formas dependiendo de lo que quieras hacer con tu objeto.
- La primera es en cuántas dimensiones estás trabajando. Las 3 de arriba en glVertex3f dice que estás dibujando en 3 dimensiones. También es posible trabajar en 2 o 4 dimensiones. La f de arriba en glVertex3f dice que está trabajando con números de coma flotante. También puedes usar cortos, enteros o dobles.
- Observe que estos puntos se definen en un en sentido anti-horario conducta. Esto no es muy importante en este momento, pero cuando empiece a trabajar con la iluminación, las texturas y el refrentado, esto se volverá increíblemente importante, así que acostúmbrese a definir sus puntos ahora en sentido contrario a las agujas del reloj.
- Agregue agregue los vértices entre las líneas glBegin () y glEnd ().
// Lado multicolor - FRONT glBegin (GL_POLYGON); glVertex3f (-0,5, -0,5, -0,5); // P1 glVertex3f (-0,5, 0,5, -0,5); // P2 glVertex3f (0.5, 0.5, -0.5); // P3 glVertex3f (0.5, -0.5, -0.5); // P4 glEnd ();
Paso 5. Agregue glColor3f ()
glColor funciona de manera similar a glVertex. Puede definir puntos como cortos, enteros, dobles o flotantes. Cada color tiene un valor de 0 a 1. Todos los 0 hacen que el punto sea negro y todos los 1 hacen que el punto sea blanco. El 3 en glColor3f () se refiere al sistema de color RGB sin canal alfa. El alfa de un color define su transparencia. Para cambiar el nivel alfa, use glColor4f () con el último parámetro siendo un valor de 0 a 1 para opaco a transparente.
- Cuando llame a glColor3f (), todos los vértices dibujados a partir de ese punto serán de ese color. Por lo tanto, si desea que los cuatro vértices sean rojos, simplemente establezca el color una vez en cualquier momento antes de los comandos glVertex3f () y todos los vértices serán rojos.
- El lado frontal definido a continuación muestra cómo definir un nuevo color para cada vértice. Al hacer esto, puede ver una propiedad interesante de los colores OpenGL. Dado que cada vértice del polígono tiene su propio color, ¡OpenGL combinará automáticamente los colores! El siguiente paso mostrará cómo asignar cuatro vértices con el mismo color.
// Lado multicolor - FRONT glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 es rojo glColor3f (0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 es verde glColor3f (0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 es azul glColor3f (1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 es púrpura glEnd ();
Paso 6. Manipule los otros lados
Calcule cuál será la ubicación de cada vértice para los otros cinco lados del cubo, pero para simplificar, estos se han calculado para usted y están incluidos en el función de visualización final () debajo.
// Lado blanco - ATRÁS glBegin (GL_POLYGON); glColor3f (1.0, 1.0, 1.0); glVertex3f (0,5, -0,5, 0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glEnd (); // Lado morado - DERECHA glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 1.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, -0,5, 0,5); glEnd (); // Lado verde - IZQUIERDA glBegin (GL_POLYGON); glColor3f (0.0, 1.0, 0.0); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); // Lado azul - TOP glBegin (GL_POLYGON); glColor3f (0.0, 0.0, 1.0); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, 0,5); glEnd (); // Lado rojo - INFERIOR glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); glFlush (); glutSwapBuffers (); }
También queremos agregar dos últimas líneas de código para esta función. Estos son glFlush ();
y glutSwapBuffers ();
lo que nos da el efecto de doble búfer del que aprendiste antes.
Parte 3 de 3: Interactividad del usuario
Paso 1. Agregue specialKeys ()
Ya casi has terminado, pero en este momento puedes dibujar un cubo pero no tienes forma de rotarlo. Para hacer esto, lo harás crear un specialKeys () función para permitirnos presionar las teclas de flecha y rotar el cubo!
- Esta función es la razón por la que declaró las variables globales rotate_x y rotate_y. Cuando presione las teclas de flecha derecha e izquierda, rotate_y aumentará o disminuirá en 5 grados. Del mismo modo, cuando presione las teclas de flecha hacia arriba y hacia abajo, rotate_x cambiará en consecuencia.
void specialKeys (int key, int x, int y) {// Flecha derecha - aumentar la rotación en 5 grados if (key == GLUT_KEY_RIGHT) rotate_y + = 5; // Flecha izquierda - disminuir la rotación en 5 grados si no (clave == GLUT_KEY_LEFT) rotate_y - = 5; de lo contrario si (clave == GLUT_KEY_UP) rotate_x + = 5; si no (clave == GLUT_KEY_DOWN) rotate_x - = 5; // Solicitar actualización de visualización glutPostRedisplay (); }
Paso 2. Agregue glRotate ()
Su última declaración es agregar la declaración que rotará su objeto. Regrese a la función display () y antes del lado FRONT, agregue estas líneas:
// Restablecer transformaciones glLoadIdentity (); // Rotar cuando el usuario cambia rotate_x y rotate_y glRotatef (rotate_x, 1.0, 0.0, 0.0); glRotatef (rotate_y, 0.0, 1.0, 0.0); // Lado multicolor - FRENTE….
Paso 3. Agregue los siguientes comandos para escalar el cubo en 2 a lo largo del eje x, 2 a lo largo del eje y, rotar el cubo 180 grados alrededor del eje y y trasladar el cubo en 0,1 a lo largo del eje x
Asegúrese de organizarlos, así como los comandos glRotate () anteriores, en el orden correcto, como se describe anteriormente. (Si no está seguro, esto se hace en el código final al final del tutorial).
// Otras transformaciones glTranslatef (0.1, 0.0, 0.0); glRotatef (180, 0.0, 1.0, 0.0); glScalef (2.0, 2.0, 0.0);
Paso 4. Compile y ejecute su código
Suponiendo que está usando gcc como su compilador, ejecute estos comandos desde su terminal para compilar y probar su programa.
En Linux: gcc cube.c -o cube -lglut -lGL./ mycube En Mac: gcc -o foo foo.c -framework GLUT -framework OpenGL./ mycube En Windows: gcc -Wall -ofoo foo.c -lglut32cu - lglu32 -lopengl32./ mycube
Paso 5. Verifique su código completo
Debería ser así:
// // Archivo: mycube.c // Autor: Matt Daisley // Creado: 25/4/2012 // Proyecto: Código fuente para Make a Cube en OpenGL // Descripción: Crea una ventana OpenGL y dibuja un cubo 3D / / Que el usuario puede rotar usando las teclas de flecha // // Controles: Flecha izquierda - Girar a la izquierda // Flecha derecha - Girar a la derecha // Flecha arriba - Girar hacia arriba // Flecha abajo - Girar hacia abajo // ------ -------------------------------------------------- - // Incluye // ------------------------------------------- --------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif // ------------- --------------------------------------------- // Prototipos de funciones / / ------------------------------------------------- --------- visualización vacía (); void specialKeys (); // ------------------------------------------------ ---------- // Variables globales // ---------------------------------- ------------------------ doble rotate_y = 0; doble rotate_x = 0; // ------------------------------------------------ ---------- // display () Función de devolución de llamada // ------------------------------- --------------------------- void display () {// Limpiar la pantalla y el búfer Z glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Restablecer transformaciones glLoadIdentity (); // Otras transformaciones // glTranslatef (0.1, 0.0, 0.0); // No incluido // glRotatef (180, 0.0, 1.0, 0.0); // No incluido // Rotar cuando el usuario cambia rotate_x y rotate_y glRotatef (rotate_x, 1.0, 0.0, 0.0); glRotatef (rotate_y, 0.0, 1.0, 0.0); // Otras transformaciones // glScalef (2.0, 2.0, 0.0); // No incluido // Lado multicolor - FRONT glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 es rojo glColor3f (0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 es verde glColor3f (0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 es azul glColor3f (1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 es púrpura glEnd (); // Lado blanco - ATRÁS glBegin (GL_POLYGON); glColor3f (1.0, 1.0, 1.0); glVertex3f (0,5, -0,5, 0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glEnd (); // Lado morado - DERECHA glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 1.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, -0,5, 0,5); glEnd (); // Lado verde - IZQUIERDA glBegin (GL_POLYGON); glColor3f (0.0, 1.0, 0.0); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, 0,5, 0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); // Lado azul - TOP glBegin (GL_POLYGON); glColor3f (0.0, 0.0, 1.0); glVertex3f (0,5, 0,5, 0,5); glVertex3f (0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, -0,5); glVertex3f (-0,5, 0,5, 0,5); glEnd (); // Lado rojo - INFERIOR glBegin (GL_POLYGON); glColor3f (1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); glVertex3f (0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, 0,5); glVertex3f (-0,5, -0,5, -0,5); glEnd (); glFlush (); glutSwapBuffers (); } // ----------------------------------------------- ----------- // función de devolución de llamada specialKeys () // ------------------------------ ---------------------------- void specialKeys (int key, int x, int y) {// Flecha derecha - aumentar la rotación en 5 grado if (clave == GLUT_KEY_RIGHT) rotate_y + = 5; // Flecha izquierda - disminuir la rotación en 5 grados si no (clave == GLUT_KEY_LEFT) rotate_y - = 5; de lo contrario si (clave == GLUT_KEY_UP) rotate_x + = 5; si no (clave == GLUT_KEY_DOWN) rotate_x - = 5; // Solicitar actualización de visualización glutPostRedisplay (); } // ----------------------------------------------- ----------- // función principal // ------------------------------- --------------------------- int main (int argc, char * argv ) {// Inicializa GLUT y procesa los parámetros de usuario glutInit (& argc, argv); // Solicitar una ventana de color verdadero con doble búfer con Z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Crear ventana glutCreateWindow ("Awesome Cube"); // Habilita la prueba de profundidad del búfer Z glEnable (GL_DEPTH_TEST); // Funciones de devolución de llamada glutDisplayFunc (display); glutSpecialFunc (teclas especiales); // Pasar el control a GLUT para eventos glutMainLoop (); // Regresar al SO return 0; }