OpenGL 立方体プログラム　環境：Visual Studio 2019　glut ライブラリ

OpenGL勉強中です。
サンプルコード実行のため環境作成して、
OpenGL 立方体プログラム　を実行しました。

# 実行サンプル
立方体の表示。
左がglDrawArray関数で描いたもの。
右がglDrawElement関数で描いたもの。
上下左右キーで回転する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423803/0cb1275e-9348-425d-89a5-18d9f0ea8847.png)

#　実行環境
windows10
VisualStudio2019
openGL glut (visual strudio nugetよりnupengl）

# 関連資料
https://github.com/sakurataiko1/Cplus_openGL/tree/main/opengl_3D_glDrawArray

# 実行手順
下記URLを参考にVisual　Studio 2019 でプロジェクト作成 ～　.cpp作成前準備までする。

https://tokoik.github.io/opengl/vs2019.pdf
「Visual Studio 2019 で NuGet を使ってからのプロジェクトから OpenGL をビルドできるプロジェクトを作る」


その後、ソースコードを書いて、実行ボタンで実行。


#ソースコード
※　#include <GL/gl.h>はコメントアウトが必要
　　読み込むライブラリはGL/glut.h　のみにする。

```
//参考：http://math.hws.edu/graphicsbook/source/glut/cubes-with-vertex-arrays.c

/* Use OpenGL to draw two cubes, one using glDrawArrays,
 * and one using glDrawElements.  The arrow keys can be
 * used to rotate both cubes.
 *
 * Note that this program does not use lighting.
 *
 * This program must be linked with the GL and GLUT libraries.
 * For example, on Linus with the gcc compiler,
 *
 *    gcc -o cubes cubes-with-vertex-arrays.c -lGL -lglut
 */

//#include <GL/gl.h>
#include <GL/glut.h>


int rotateX = 15, rotateY = -15, rotateZ = 0;  // rotation amounts about axes, controlled by keyboard


/* Arrays for use with glDrawElements.  This is the data for a cube with 6 different
 * colors at the six vertices.  (Looks kind of strange without lighting.)
 */

float vertexCoords[24] = {  // Coordinates for the vertices of a cube.
           1,1,1,   1,1,-1,   1,-1,-1,   1,-1,1,
          -1,1,1,  -1,1,-1,  -1,-1,-1,  -1,-1,1 };

float vertexColors[24] = {  // An RGB color value for each vertex
           1,1,1,   1,0,0,   1,1,0,   0,1,0,
           0,0,1,   1,0,1,   0,0,0,   0,1,1 };

int elementArray[24] = {  // Vertex number for the six faces.
          0,1,2,3, 0,3,7,4, 0,4,5,1,
          6,2,1,5, 6,5,4,7, 6,7,3,2 };


/* We will draw edges for the first cube using this array with glDrawElements.
 * (It looks pretty bad without lighting if edges aren't drawn.
 */

int edgeElementArray[24] = {
        0,1,  1,5,  5,4,  4,0,    // edges of the top face
        7,3,  3,2,  2,6,  6,7,    // edges of the bottom face
        1,2,  0,3,  4,7,  5,6 }; // edges connecting top face to bottom face

/* Arrays for use with glDrawArrays.  The coordinate array contains four sets of vertex
 * coordinates for each face.  The color array must have a color for each vertex.  Since
 * the color of each face is solid, there is a lot of redundancy in the color array.
 * There is also redundancy in the coordinate array, compared to using glDrawElements.
 * But note that it is impossible to use a single call to glDrawElements to draw a cube
 * with six faces where each face has a different solid color, since with glDrawElements,
 * the colors are associated with the vertices, not the faces.
 */

float cubeCoords[72] = {
       1,1,1,    -1,1,1,   -1,-1,1,   1,-1,1,      // face #1
       1,1,1,     1,-1,1,   1,-1,-1,  1,1,-1,      // face #2
       1,1,1,     1,1,-1,  -1,1,-1,  -1,1,1,       // face #3
       -1,-1,-1, -1,1,-1,   1,1,-1,   1,-1,-1,     // face #4
       -1,-1,-1, -1,-1,1,  -1,1,1,   -1,1,-1,      // face #5
       -1,-1,-1,  1,-1,-1,  1,-1,1,   -1,-1,1 };  // face #6

float cubeFaceColors[72] = {
        1,0,0,  1,0,0,  1,0,0,  1,0,0,      // face #1 is red
        0,1,0,  0,1,0,  0,1,0,  0,1,0,      // face #2 is green
        0,0,1,  0,0,1,  0,0,1,  0,0,1,      // face #3 is blue
        1,1,0,  1,1,0,  1,1,0,  1,1,0,      // face #4 is yellow
        0,1,1,  0,1,1,  0,1,1,  0,1,1,      // face #5 is cyan
        1,0,1,  1,0,1,  1,0,1,  1,0,1, }; // face #6 is red

//----------------------------------------------------
// 関数プロトタイプ（後に呼び出す関数名と引数の宣言）
//----------------------------------------------------
void display();
void specialKeyFunction(int key, int x, int y);
void initGL(); 
//----------------------------------------------------
// メイン関数
//----------------------------------------------------
// ----------------------------------------------------------------------
int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(600, 300);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("USE ARROW KEYS TO ROTATE; HOME KEY RESETS");
    initGL();
    glutDisplayFunc(display);
    glutSpecialFunc(specialKeyFunction);
    glutMainLoop();
    return 0;
}


void display() {
    // called when the display needs to be drawn

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();             // Set up modelview transform, first cube.
    glTranslatef(-2, 0, 0);     // Move cube to left half of window.

    glRotatef(rotateZ, 0, 0, 1);     // Apply rotations.
    glRotatef(rotateY, 0, 1, 0);
    glRotatef(rotateX, 1, 0, 0);

    glVertexPointer(3, GL_FLOAT, 0, cubeCoords);  // Set data type and location, first cube.
    glColorPointer(3, GL_FLOAT, 0, cubeFaceColors);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glDrawArrays(GL_QUADS, 0, 24); // Draw the first cube!


    // Second cube, using glDrawElements.  Also draw the cube edges, and enable polygon offset
    // while the faces of the cube are being drawn.

    glLoadIdentity();             // Set up modelview transform, first cube.

    glTranslatef(2, 0, 0);      // Move cube to right half of window.

    glRotatef(rotateZ, 0, 0, 1);     // Apply rotations.
    glRotatef(rotateY, 0, 1, 0);
    glRotatef(rotateX, 1, 0, 0);

    glVertexPointer(3, GL_FLOAT, 0, vertexCoords);  // Set data type and location, second cube.
    glColorPointer(3, GL_FLOAT, 0, vertexColors);


    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1, 1);
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, elementArray); // Draw the second cube!
    glDisable(GL_POLYGON_OFFSET_FILL);

    glDisableClientState(GL_COLOR_ARRAY);  // Don't use color array for the edges.
    glColor3f(0, 0, 0);  // The edges will be black.
    glLineWidth(2);

    glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, edgeElementArray);  // Draw the edges!

    glutSwapBuffers();
}


void specialKeyFunction(int key, int x, int y) {
    // called when a special key is pressed 
    if (key == GLUT_KEY_LEFT)
        rotateY -= 15;
    else if (key == GLUT_KEY_RIGHT)
        rotateY += 15;
    else if (key == GLUT_KEY_DOWN)
        rotateX += 15;
    else if (key == GLUT_KEY_UP)
        rotateX -= 15;
    else if (key == GLUT_KEY_PAGE_UP)
        rotateZ += 15;
    else if (key == GLUT_KEY_PAGE_DOWN)
        rotateZ -= 15;
    else if (key == GLUT_KEY_HOME)
        rotateX = rotateY = rotateZ = 0;
    glutPostRedisplay();
}

void initGL() {
    // called by main() to do initialization for this program.
    glMatrixMode(GL_PROJECTION);
    glOrtho(-4, 4, -2, 2, -2, 2);  // simple orthographic projection
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.5, 0.5, 0.5, 1);
}
```

#実行
visual Strudio の　実行ボタンで実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423803/7abd753f-a160-420b-e32b-31981e752d31.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423803/0cb1275e-9348-425d-89a5-18d9f0ea8847.png)

#補足
手順の前に、環境整備として、glutのインストールとして下記もした。
（多分以下は不要でも動作するはずだが補足まで。）

Windows 32bit向けのファイルをNate Robins氏のサイトからダウンロードする。
READMEに従って次のようにコピーする。

| ファイル |	コピー先 |
| ---- | ---- |  ---- |
| glut.h |  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\XX.XX.XXXXX\include\GL\ | include フォルダ内にGLフォルダを作成 |
|  glut32.lib  |  C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\XX.XX.XXXXX\lib\x86\  | _ |
| glut32.dll  |  ‪C:\Windows\System\  |  コンパイル済ファイルの実行に必要 |