Code

ここで使われているライブラリはこのページからgetしてね。

#include <stdio.h>
#include <miffy/glutility.h>
 
#include <GL/freeglut.h>
#include <string>
#include <iostream>
#include <fstream>
#include <float.h>
#include <Windows.h>
#include <assert.h>
#define _USE_MATH_DEFINES 
#include <math.h>//クォータニオンに必要
#include <miffy/math/matrix.h>
#include <miffy/math/quaternion.h>
#include <miffy/math/vertex.h>
#include <miffy/file.h>
#include <miffy/model/ply.h>
#include <miffy/math/triangle.h>
using namespace std;
//const char* FILENAME= "../../data/happy_recon/happy_vrip_res4.ply";
//const char* FILENAME= "../../data/dragon_recon/dragon_vrip_res4.ply";
const char* FILENAME= "../data/bun_zipper_res4.ply";
bool quaternionflag=false;
const int WINWIDTH =600;
const int WINHEIGHT =600;
float background[3]={0.0,0.0,0.0};//背景色
float myrotate[3]={0.0,0.0,0.0};
float translate_speed=0.01;
float zoom_speed=0.2;
float eyePoint[3]={0.0,0.0,1.0};
miffy::quat<float> current_quaternion(1.0,0.0,0.0,0.0);
miffy::quat<float> target_quaternion;
int previous_x;
int previous_y;
int mouse_down[2];
miffy::mat4<float> rotate;
//回転マトリックス
//平行移動
float trans[3]={0,0,-0.2};
float area=1.0;
float offset=-0.5;
float offsetz=10;
float aspectratio=1.0;//y/xデータの縦横比
//debug情報
//回転行列
miffy::mat4<float> rotation_matrix;
miffy::SModel model;
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(){
        miffy::LoadPlyData(&model,FILENAME);
        glEnableClientState(GL_COLOR_ARRAY);        
        glColorPointer(4,GL_FLOAT,sizeof(miffy::vertex<float>),&model.verts[0].r);
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3,GL_FLOAT,sizeof(miffy::vertex<float>),&model.verts[0].x);
 
        //どうやって法線を計算するか???
        for(int i=0;i<model.facenum;i++){
            miffy::tri<float> tri(model.verts[model.indices[i*3+0]],model.verts[model.indices[i*3+1]],model.verts[model.indices[i*3+2]]);
            miffy::vec3<float> normal=tri.CalcNormalVector<float>();
            model.verts[model.indices[i*3+0]].SetNormalVector(normal);
        }
        glEnableClientState(GL_NORMAL_ARRAY);
        glNormalPointer(GL_FLOAT,sizeof(miffy::vertex<float>),&model.verts[0].nx);
    }
    void InitCamera(){
        current_quaternion.toMat4(rotation_matrix.m);
    }
    void Destroy(){
    }
    void idle(){
        glutPostRedisplay();
    }
    void reshape (int w, int h)
    {
        //射影変換行列
        glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity (); 
        gluPerspective(30.0, (float)w / (float)h, 0.01, 4.0);
        glMatrixMode (GL_MODELVIEW);
    }
    void DrawModel(miffy::SModel* _model){
        //initに移すとおかしくなる。why?
        //glPointSize(1);
        glPushMatrix();
        glTranslatef(0.03,-0.07,0.0);
        glColor3f(1.0,1.0,1.0);        
        glDrawElements(GL_TRIANGLES,_model->facenum*3,GL_UNSIGNED_INT,_model->indices);
        glPopMatrix();
    }
    void DrawBoundingBox(){
        glColor3f(1.0,1.0,1.0);
        glPointSize(10);
        drawWireCube(0.3);
    }
    void Init(){
        InitGeometry();
        InitLights();
 
        InitCamera();
        printf("end init\n");
 
    }
    void display(void)
    {
        glClearColor(background[0],background[1], background[2], 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    
        glEnable(GL_DEPTH_TEST);
 
        glLoadIdentity ();/* clear the matrix */
        gluLookAt (eyePoint[0], eyePoint[1], eyePoint[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);//zが上であるが、そうするのが難しい。
        glPushMatrix();
        glTranslatef(trans[0],trans[1],trans[2]);//平行移動
        glMultMatrixf(rotation_matrix.m);//クォータニオンによる回転
        DrawModel(&model);
        //DrawCoordinate(0.5);
        DrawBoundingBox();    
        glPopMatrix();
        glutSwapBuffers();
 
    }
    void key(unsigned char key , int x , int y) {
        //printf("key=%d\n",key);
        switch(key){
        case '+':
            trans[2]+=zoom_speed;
            break;
        case '-':
            trans[2]-=zoom_speed;
            break;
        }
        printf("zoom%f\n",trans[2]);
        glutPostRedisplay();
    }
    void wheel(int button, int direction, int x, int y) 
    { 
        if(direction>0){
            trans[2]-=zoom_speed;
        }else{
            trans[2]+=zoom_speed;
        }
        glutPostRedisplay();
    }
    void mouse(int button , int state , int x , int y) {
 
        if(button == GLUT_RIGHT_BUTTON){//平行移動
 
            quaternionflag=false;
            if(state==GLUT_DOWN){
                mouse_down[0]=x;
                mouse_down[1]=y;
                //printf("down:%d,%d\n",x,y);
            }else if(state==GLUT_UP){
                trans[0]+=translate_speed*(x-mouse_down[0]);
                trans[1]+=-translate_speed*(y-mouse_down[1]);//yは上下逆
                //printf("up:%d,%d\n",x,y);
            }
 
        }
        else 
            if(button == GLUT_LEFT_BUTTON){
                quaternionflag=true;
                switch(state){        
                case GLUT_DOWN://Quaternion:マウスボタンを押した位置を記憶 
                    previous_x = x;
                    previous_y = y;
                case GLUT_UP://Quaternion:姿勢を保存
                    current_quaternion=target_quaternion;
 
                    break;
                default:
                    break;
                }
 
            }
            glutPostRedisplay();
 
    }
    //http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20040321
    void move(int x, int y)
    {
        if(quaternionflag){
            //移動量を計算 画面の中で何%ぐらい動いたか?
            float dx = (x - previous_x) * 1.0/WINWIDTH;
            float dy = (y - previous_y) * 1.0/WINHEIGHT;
 
            //クォータニオンの長さ
            float length = sqrt(dx * dx + dy * dy);
 
            if (length != 0.0) {
                //M_PIは適当な換算係数 piにしておくと、画面いっぱい動かした時にちょうど一回転になる
                float radian = length * M_PI;
                float theta = sin(radian) / length;
                miffy::quat<float> after( cos(radian), dy * theta, dx * theta, 0.0);//回転後の姿勢
                target_quaternion = after * current_quaternion;
                target_quaternion.toMat4(rotation_matrix.m);
 
            }
        }else{//平行移動
            trans[0]+=translate_speed*(x-mouse_down[0]);
            trans[1]+=-translate_speed*(y-mouse_down[1]);//yは上下逆
            mouse_down[0]=x;
            mouse_down[1]=y;
        }
    }
    int main(int argc, char *argv[])
    {
        glutInit(&argc, argv);
        //glutMainLoopから抜け出してから何か表示するためのもの
        glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);
        glutInitWindowSize (WINWIDTH, WINHEIGHT); 
        glutInitWindowPosition (0, 0);
        glutCreateWindow("miffy program");
        glewInit();
        Init();
 
        glutDisplayFunc(display);
        glutIdleFunc(idle);
 
        glutReshapeFunc(reshape);
        glutKeyboardFunc(key);
        glutMouseFunc(mouse);
        glutMotionFunc(move);
        glutMouseWheelFunc(wheel);
        glutMainLoop();
 
        printf("終了");
        exit(0);
        return 0;
    }
サポートサイト Wikidot.com