うさちゃんを表示するコード

ply-code.png
ここで使われているライブラリはこのgitリポジトリからgetしてね。
#define _USE_MATH_DEFINES
#include <cmath>
#include <fstream>
#include <cassert>
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>
#include <sstream>
#include <numeric>
using namespace std;
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <GL/freeglut.h>
 
#include <miffy/math/vec2.h>
#include <miffy/fileformat/ply.h>
#include <miffy/glfw/glfwlistener.h>
#include <miffy/math/triangle.h>
const char* FILENAME = "../../../../data/bun_zipper.ply";
 
using namespace miffy;
class Rotate :public MouseState {
public:
    void run() {}
    void stop() {}
};
class Translate :public MouseState {
public:
    void run() {}
    void stop() {}
};
 
class MiffyOpengl :GLFWListener {
public:
    vec2<float> m_translate;
    vec2<int> m_win_size;
    vec2<int> m_last_pushed;
    quat<float> m_current_quaternion;
    quat<float> m_target_quaternion;
 
    mat4<float> m_modelview;
    mat4<float> m_rotation_matrix;
    mat4<float> m_proj_matrix;
    mat4<float> m_inv_modelview;
    mat4<float> m_inv_next_modelview;
    mat4<float> m_next_modelview;
    double m_zoom;
    const   vec3<double> m_world_eye_pos;//ワールド座標での視点座標
    const float m_near;
    const float m_far;
    const float m_fovy;
    float m_aspect_ratio;
    MouseState &m_Mouse;
    Rotate mRotate;
    Translate mTranslate;
    enum Move { QUIET, ROTATING, END_ROTATE, SHIFT, END_SHIFT };
    Move m_currentState;
 
    Ply model;
 
    MiffyOpengl(void) 
        :m_world_eye_pos(vec3<double>(0.0, 0.0, 0.6))
        , m_near(0.1f)
        , m_far(100.0f)
        , m_fovy(30.0f)
        , m_currentState(QUIET)
        , m_Mouse(mTranslate){
        m_zoom = m_world_eye_pos.z;
    }
    void init(GLFWwindow* _glfw_window) {
        glfwSetWindowUserPointer(_glfw_window,this);
        glEnable(GL_MULTISAMPLE);
        glfwSetScrollCallback(_glfw_window, wheel);
        glfwSetWindowSizeCallback(_glfw_window, miffy::reshape);
        glfwSetMouseButtonCallback(_glfw_window, miffy::mousebutton);
        glfwSetCursorPosCallback(_glfw_window, miffy::mousemove);
        glfwSetKeyCallback(_glfw_window, keyCallback);
 
        InitLights();
 
        glShadeModel(GL_FLAT);
        InitGeometry();
 
    }
 
    void initShader() {
        ifstream is("shader.vert", ios::ate);//開く時にEOFまで移動する
        int length = int(is.tellg()) - 1;
        is.seekg(0, is.beg);
        char* vertex_shader_chars = new char[length];
        is.read(vertex_shader_chars, length);
        is.close();
        vertex_shader_chars[length - 1] = '\0';
 
        is.open("shader.frag", ios::ate);
        length = int(is.tellg()) - 1;
        is.seekg(0, is.beg);
        char* fragment_shader_chars = new char[length];
        is.read(fragment_shader_chars, length);
        is.close();
        fragment_shader_chars[length - 1] = '\0';
        gProgram = createShaderProgram(vertex_shader_chars, fragment_shader_chars);
 
    }
    void InitLights() {
        glEnable(GL_DEPTH_TEST);
        //glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4,0, 1, 12, 4, &model.verts[0].x);
        //glEnable(GL_MAP2_VERTEX_3);
        glEnable(GL_AUTO_NORMAL);
        //glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0);
 
        GLfloat ambient[] = { 0.2,0.2,0.2,1.0 };
        GLfloat position[] = { 0.0,0.0,2.0,1.0 };
        GLfloat mat_diffuse[] = { 0.6,0.6,0.6,1.0 };
        GLfloat mat_specular[] = { 1.0,1.0,1.0,1.0 };
        GLfloat mat_shiness[] = { 50.0 };
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
        glLightfv(GL_LIGHT0, GL_POSITION, position);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
        glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
        glMaterialfv(GL_FRONT, GL_SHININESS, mat_shiness);
    }
    void InitGeometry() {
        model.LoadPlyData(FILENAME);
 
        model.m_Normals = new vec3<float>[model.mVertNum];
        //どうやって法線を計算するか???
        for (int i = 0; i<model.mTriangleNum; i++) {
            tri<float> tri(model.m_Verts[model.m_Indices[i * 3 + 0]], model.m_Verts[model.m_Indices[i * 3 + 1]], model.m_Verts[model.m_Indices[i * 3 + 2]]);
            vec3<float> normal = tri.CalcNormalVector<float>();
            model.m_Normals[model.m_Indices[i * 3 + 0]]=normal;
        }
 
    }
    void DrawModel() {
 
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, sizeof(miffy::vec3<float>), &model.m_Verts[0].x);
        glEnableClientState(GL_COLOR_ARRAY);
        glColorPointer(4, GL_FLOAT, sizeof(miffy::color<float>), &model.m_Colors[0].r);
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT, sizeof(miffy::vec3<float>), &model.m_Normals[0].x);
 
        glPushMatrix();
 
        glTranslatef(0.03, -0.07, 0.0);
 
        glDrawElements(GL_TRIANGLES, model.mTriangleNum * 3, GL_UNSIGNED_INT, model.m_Indices);
        glPopMatrix();
 
        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
    }
    static void GetGLError(const char* op) {
        for (GLint error = glGetError(); error; error = glGetError()) {
            printf("after %s() glErrorCode:%x=%s\n", op, error, gluErrorString(error));
            assert(!"!glError\n");
        }
    }
    /**
     * @brief 画面上に文字を出力する関数
     */
    void print(void* font, float x, float y, stringstream* message) {
        glRasterPos2d(x, y);//スタート位置
        glutBitmapString(font, reinterpret_cast<const unsigned char*>(message->str().c_str()));
    }
    void display() {
        glClearColor(0.0, 0.0, 0.0, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        gluLookAt(m_world_eye_pos.x, m_world_eye_pos.y, m_zoom, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
        glTranslated(m_translate.x, m_translate.y, 0.0);/* 平行移動(奥行き方向)   */
        m_target_quaternion.toMat4(const_cast<float*>(m_rotation_matrix.m));
        glMultMatrixf(m_rotation_matrix.m);//クォータニオンによる回転
 
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_LINE_SMOOTH);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
 
        DrawModel();
 
        glDisable(GL_BLEND);
        glDisable(GL_LINE_SMOOTH);
        glDisable(GL_DEPTH_TEST);
        glPopMatrix();
    }
 
    static void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
    {
        if (action == GLFW_PRESS) {
            switch (key)
            {
            case GLFW_KEY_ESCAPE:// ESCキーでウィンドウのクローズフラグを設定。
                // Sets the close flag of the specified window.
                glfwSetWindowShouldClose(window, GL_TRUE);
                break;
            }
        }
    }
    void reshape(int _width, int _height) {
        m_win_size.x = _width;
        m_win_size.y = _height;
 
        glViewport(0, 0, (GLsizei)m_win_size.x, (GLsizei)m_win_size.y);
 
        m_aspect_ratio = (float)m_win_size.x / (float)m_win_size.y;
 
        //ブロック前後クリッピング初期化
        glMatrixMode(GL_PROJECTION);  /* 投影変換の設定 */
        glLoadIdentity();
        float ratio = m_win_size.x / (float)m_win_size.y;
        gluPerspective(m_fovy, m_aspect_ratio, m_near, m_far);//original
        glGetFloatv(GL_PROJECTION_MATRIX, m_proj_matrix.m);
        glMatrixMode(GL_MODELVIEW);
 
    }
 
    void RotateFromScreen(int _mx, int _my) {
        float dx = (float)(_mx - m_last_pushed.x) / (float)m_win_size.x;
        float dy = (float)(_my - m_last_pushed.y) / (float)m_win_size.y;
        //過去との回転の合成をどうやっていいかわからない。やっぱクオータニオンが必要
        vec3<float> rotate_axis = vec3<float>(dy, dx, 0.0);
        float axislength = rotate_axis.length();
        if (axislength != 0.0) {
            float radian = (float)fmod(axislength*(float)M_PI, 360.0);//画面いっぱいで調度一周になるようにする。
            rotate_axis.normalize();//軸の長さを1にする。
            quat<float> difq(cos(radian), rotate_axis.x*sin(radian), rotate_axis.y*sin(radian), 0.0);
            m_target_quaternion = difq*m_current_quaternion;
        }
    }
    void mousemove( double _mx, double _my) {
        static vec2<int> tra_lastpush;
        if (m_Mouse.m_current_button == GLFW_MOUSE_BUTTON_LEFT) {
            if (m_Mouse.m_button_state == GLFW_PRESS) {
                RotateFromScreen(_mx, _my);
            }
            else {//回転やめ
                m_last_pushed.set(_mx, _my);
                m_current_quaternion = m_target_quaternion;
            }
        }
        else
            if (m_Mouse.m_current_button == GLFW_MOUSE_BUTTON_RIGHT) {//平行移動
                if (m_Mouse.m_button_state == GLFW_PRESS) {
                    m_translate.x += (float)(_mx - tra_lastpush.x) / (float)m_win_size.x;
                    m_translate.y += (float)(_my - tra_lastpush.y)*-1.0f / (float)m_win_size.y;
                    tra_lastpush.set(_mx, _my);
                }
                else {
                    tra_lastpush.set(_mx, _my);
                }
            }
    }
    void mousebutton(int _button, int _action, int mods) {
        m_Mouse.m_current_button = _button;
        m_Mouse.m_button_state = _action;
        if (_action == GLFW_RELEASE) {
            m_Mouse.stop();
            return;
        }
 
    }
    void zoom(int _direction){
 
        m_zoom+=(double)_direction*0.4;
        cout << m_zoom << endl;
    }
 
};
MiffyOpengl opengl;
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glfwInit();
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_RED_BITS, 8);
    glfwWindowHint(GLFW_GREEN_BITS, 8);
    glfwWindowHint(GLFW_BLUE_BITS, 8);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);
    GLFWwindow* window = glfwCreateWindow(300, 300, "Hello GLSL", nullptr, nullptr);
 
    glfwMakeContextCurrent(window);
    glewInit();
    opengl.init(window);
 
    while (!glfwWindowShouldClose(window))
    {
        //reshapeのコールバックが効かなかったので暫定対応
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        opengl.reshape(width,height);
        opengl.display();
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
 
    glfwTerminate();
    return 0;
}

サポートサイト Wikidot.com