[kaze's test] プログラミングメモ
テクスチャー直方体回転(vc++2017 openGL)

→目次

vc++2017 freeglutでopenGLの勉強メモです。gdiplusで画像ファイルからテクスチャーを読み込んで直方体に貼り付けます。キーボードとタイマーを使ってX軸Y軸Z軸のオイラー角の変化を起こします。オイラー角から回転行列を作成し、直方体の回転を実現します。


#include <math.h>
#pragma comment (lib, "Gdiplus.lib")
#include <objbase.h>
#include <GL/freeglut.h>
#include <stdio.h>
#include <gdiplus.h>
#include <iostream>

using namespace Gdiplus;
#define WIDTH 400
#define HEIGHT 300

GdiplusStartupInput gdiPSI;
ULONG_PTR gdiPT;
GLuint textures[6];

GLfloat translate[] = {
    1 , 0 , 0 , 0 ,
    0 , 1 , 0 , 0 ,
    0 , 0 , 1 , 0 ,
    0 , 0 , 0 , 1
};

enum VIEW_SIDE
{
    VIEW_RIGHT,
    VIEW_LEFT,
    VIEW_BACK,
    VIEW_FRONT,
    VIEW_TOP,
    VIEW_BOTTOM
};
const wchar_t* filenames[6] = { L"right.png", L"left.png", L"back.png", L"front.png", L"top.png", L"bottom.png" };

void Cube(float halfXdimension, float halfYdimension, float halfZdimension)
{
    // Right
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glBegin(GL_QUADS);
    glNormal3f(1, 0, 0); glTexCoord2f(0, 1); glVertex3f(halfXdimension, -halfYdimension, -halfZdimension);
    glNormal3f(1, 0, 0); glTexCoord2f(0, 0); glVertex3f(halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(1, 0, 0); glTexCoord2f(1, 0); glVertex3f(halfXdimension, halfYdimension, halfZdimension);
    glNormal3f(1, 0, 0); glTexCoord2f(1, 1); glVertex3f(halfXdimension, halfYdimension, -halfZdimension);
    glEnd();

    // Left
    glBindTexture(GL_TEXTURE_2D, textures[1]);
    glBegin(GL_QUADS);
    glNormal3f(-1, 0, 0); glTexCoord2f(1, 1); glVertex3f(-halfXdimension, -halfYdimension, -halfZdimension);
    glNormal3f(-1, 0, 0); glTexCoord2f(1, 0); glVertex3f(-halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(-1, 0, 0); glTexCoord2f(0, 0); glVertex3f(-halfXdimension, halfYdimension, halfZdimension);
    glNormal3f(-1, 0, 0); glTexCoord2f(0, 1); glVertex3f(-halfXdimension, halfYdimension, -halfZdimension);
    glEnd();

    // Back
    glBindTexture(GL_TEXTURE_2D, textures[2]);
    glBegin(GL_QUADS);
    glNormal3f(0, 1, 0); glTexCoord2f(1, 1); glVertex3f(-halfXdimension, halfYdimension, -halfZdimension);
    glNormal3f(0, 1, 0); glTexCoord2f(1, 0); glVertex3f(-halfXdimension, halfYdimension, halfZdimension);
    glNormal3f(0, 1, 0); glTexCoord2f(0, 0); glVertex3f(halfXdimension, halfYdimension, halfZdimension);
    glNormal3f(0, 1, 0); glTexCoord2f(0, 1); glVertex3f(halfXdimension, halfYdimension, -halfZdimension);
    glEnd();

    // Front
    glBindTexture(GL_TEXTURE_2D, textures[3]);
    glBegin(GL_QUADS);
    glNormal3f(0, -1, 0); glTexCoord2f(0, 1); glVertex3f(-halfXdimension, -halfYdimension, -halfZdimension);
    glNormal3f(0, -1, 0); glTexCoord2f(0, 0); glVertex3f(-halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(0, -1, 0); glTexCoord2f(1, 0); glVertex3f(halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(0, -1, 0); glTexCoord2f(1, 1); glVertex3f(halfXdimension, -halfYdimension, -halfZdimension);
    glEnd();

    // Top
    glBindTexture(GL_TEXTURE_2D, textures[4]);
    glBegin(GL_QUADS);
    glNormal3f(0, 0, 1); glTexCoord2f(0, 1); glVertex3f(-halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(0, 0, 1); glTexCoord2f(1, 1); glVertex3f(halfXdimension, -halfYdimension, halfZdimension);
    glNormal3f(0, 0, 1); glTexCoord2f(1, 0); glVertex3f(halfXdimension, halfYdimension, halfZdimension);
    glNormal3f(0, 0, 1); glTexCoord2f(0, 0); glVertex3f(-halfXdimension, halfYdimension, halfZdimension);
    glEnd();

    // Bottom
    glBindTexture(GL_TEXTURE_2D, textures[5]);
    glBegin(GL_QUADS);
    glNormal3f(0, 0, -1); glTexCoord2f(0, 0); glVertex3f(-halfXdimension, -halfYdimension, -halfZdimension);
    glNormal3f(0, 0, -1); glTexCoord2f(1, 0); glVertex3f(halfXdimension, -halfYdimension, -halfZdimension);
    glNormal3f(0, 0, -1); glTexCoord2f(1, 1); glVertex3f(halfXdimension, halfYdimension, -halfZdimension);
    glNormal3f(0, 0, -1); glTexCoord2f(0, 1); glVertex3f(-halfXdimension, halfYdimension, -halfZdimension);
    glEnd();
}
void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
    glLoadIdentity();
    glPolygonMode(GL_FRONT, GL_FILL);

    glTranslatef(0, 0, -90.0f);

    VIEW_SIDE vs = VIEW_FRONT;
    switch (vs)
    {
    case (VIEW_RIGHT):
        glRotatef(-90, 0, 1, 0);
        glRotatef(-90, 1, 0, 0);
        break;
    case (VIEW_LEFT):
        glRotatef(90, 0, 1, 0);
        glRotatef(-90, 1, 0, 0);
        break;
    case (VIEW_BACK):
        glRotatef(90, 1, 0, 0);
        glRotatef(180, 0, 1, 0);
        break;
    case (VIEW_FRONT):
        glRotatef(-90, 1, 0, 0);
        break;
    case (VIEW_TOP):
        break;
    case (VIEW_BOTTOM):
        glRotatef(180, 1, 0, 0);
        break;
    }

    glPushMatrix();
    glMultMatrixf(translate);                         
    Cube(5.0, 4.0, 3.0);
    glPopMatrix();
    glFlush();
    glutSwapBuffers();
}

void idle(void)
{
}

double x = 0.0;
double y = 0.0;
double z = 0.0;

double dx = 0.0;
double dy = 0.0;
double dz = 0.0;
void timer(int value)
{
    x += dx;
    y += dy;
    z += dz;

    double R11 = cos(y) * cos(z);
    double R12 = sin(x)*sin(y)*cos(z) - cos(x) * sin(z);
    double R13 = cos(x) * sin(y) * cos(z) + sin(x) * sin(z);
    
    double R21 = cos(y)*sin(z);
    double R22 = sin(x) * sin(y) * sin(z) + cos(x) * cos(z);
    double R23 = cos(x) * sin(y) * sin(z) - sin(x) * cos(z);

    double R31 = -sin(y);
    double R32 = sin(x)*cos(y);
    double R33 = cos(x) * cos(y);

    translate[0] = (float)R11;
    translate[1] = (float)R21;
    translate[2] = (float)R31;
    translate[4] = (float)R12;
    translate[5] = (float)R22;
    translate[6] = (float)R32;
    translate[8] = (float)R13;
    translate[9] = (float)R23;
    translate[10] = (float)R33;

    glutPostRedisplay();
    glutTimerFunc(10, timer, 0);
}
void Keyboard(unsigned char key, int _x, int _y) {
    switch (key)
    {
    case 'x':
        dx = 0.01;
        dy = 0.0;
        dz = 0.0;
        std::cout << " X軸回転 ..." << std::endl;
        break;
    case 'y':
        dx = 0.0;
        dy = 0.01;
        dz = 0.0;
        std::cout << " Y軸回転 ..." << std::endl;
        break;
    case 'z':
        dx = 0.0;
        dy = 0.0;
        dz = 0.01;
        std::cout << " Z軸回転 ..." << std::endl;
        break;
    case '-':
        dx = -dx;
        dy = -dy;
        dz = -dz;
        std::cout << " 逆転 ..." << std::endl;
        break;
    case 's':
        dx = 0.0;
        dy = 0.0;
        dz = 0.0;
        break;
    case '0':
        dx = 0.0;
        dy = 0.0;
        dz = 0.0;
        x = 0.0;
        y = 0.0;
        z = 0.0;
        break;
    case 'q':
        exit(0);
        break;
    default:
        break;
    }
}

void LoadImage(const wchar_t* filename, GLuint &texture)
{
    glEnable(GL_TEXTURE_2D);
    Bitmap bmp(filename);
    BitmapData data;
    Status st = bmp.LockBits(0, ImageLockModeRead, PixelFormat32bppARGB, &data);
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, 4, data.Width, data.Height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data.Scan0);
    glBindTexture(GL_TEXTURE_2D, 0);
    bmp.UnlockBits(&data);
}

void Init() {
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_TEXTURE_2D);                                      
    glEnable(GL_NORMALIZE);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_DEPTH_TEST);                         
    glEnable(GL_BLEND);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);     
    GdiplusStartup(&gdiPT, &gdiPSI, NULL);
    for (int i = 0; i < 6; i++) {
        LoadImage(filenames[i], textures[i]);
    }
}


void Resize(int width, int height)
{
    glViewport(0, 0, width, height);
    glPushMatrix();
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(10, (float)width / (float)height, 1.0, 250.0);

    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

void end()
{
    GdiplusShutdown(gdiPT);
}

int main(int argc, char *argv[])
{
    atexit(end);
    glutInitWindowPosition(10, 100);
    glutInitWindowSize(WIDTH, HEIGHT);
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutCreateWindow("テクスチャー立方体回転");
    glutDisplayFunc(display);
    glutIdleFunc(idle);
    glutTimerFunc(10, timer, 0);
    glutReshapeFunc(Resize);
    glutKeyboardFunc(Keyboard);
    Init();
    glutMainLoop();
    return 0;
}