基于arcball四元数旋转矩阵略微偏离我的立方体的旋转

时间:2012-10-18 22:30:03

标签: c++ opengl quaternions

我试图根据弧形鼠标移动使用四元数旋转我的立方体到矩阵旋转。我的立方体正在渲染,它有移动/旋转,但它不仅仅是围绕一个轴旋转,它也是朝我的鼠标方向移动,所以我认为我从轨迹球得到的数据有点偏或者将我的四元数转换为旋转矩阵的方式稍微偏离。 trackball_ptov是我将鼠标位置转换为弧形球的地方。 mouseMotion()是从四元数中创建旋转矩阵的地方。

我的主要内容:

#include "Angel.h"
#include <gl/glew.h>
#include <glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
using namespace std;

#define bool int  /* if system does not support bool type */
#define false 0
#define true 1
#define M_PI 3.14159265358 /* if not in math.h */
int winWidth, winHeight;
float angle = 0.0, axis[3], trans[3];
bool trackingMouse = false;
float lastPos[3] = {0.0, 0.0, 0.0};
float aspect = 1.0;
int curx, cury;
int startX, startY;
int modelInit=1;
//the program object
GLuint program = 0;
 glm::mat4 model;

typedef Angel::vec4 color4;
typedef Angel::vec4 point4;
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
color4 colors[NumVertices];

enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLuint mvpUniform;
GLuint shaderaxis;
int Index = 0;


// Vertices of a unit cube centered at origin, sides aligned with axes
point4 vertices[8]={
        point4(-0.5, -0.5, 0.5, 1.0),
        point4(-0.5, 0.5, 0.5, 1.0),
        point4(0.5, 0.5, 0.5, 1.0),
        point4(0.5, -0.5, 0.5, 1.0),
        point4(-0.5, -0.5, -0.5, 1.0),
        point4(-0.5, 0.5, -0.5, 1.0),
        point4(0.5, 0.5, -0.5, 1.0),
        point4(0.5, -0.5, -0.5, 1.0)
};

// RGBA colors
color4 vertex_colors[8] = {
        color4(0.0, 0.0, 0.0, 1.0), // black
        color4(1.0, 0.0, 0.0, 1.0), // red
        color4(1.0, 1.0, 0.0, 1.0), // yellow
        color4(0.0, 1.0, 0.0, 1.0), // green
        color4(0.0, 0.0, 1.0, 1.0), // blue
        color4(1.0, 0.0, 1.0, 1.0), // magenta
        color4(1.0, 1.0, 1.0, 1.0), // white
        color4(0.0, 1.0, 1.0, 1.0) // cyan
};

// quad generates two triangles for each face and assigns colors to the vertices
void quad(int a, int b, int c, int d) {
        colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
        colors[Index] = vertex_colors[b]; points[Index] = vertices[b]; Index++;
        colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
        colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
        colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
        colors[Index] = vertex_colors[d]; points[Index] = vertices[d]; Index++;
}

// generate 12 triangles: 36 vertices and 36 colors
void colorcube(void) {
        quad(1, 0, 3, 2);
        quad(2, 3, 7, 6);
        quad(3, 0, 4, 7);
        quad(6, 5, 1, 2);
        quad(4, 5, 6, 7);
        quad(5, 4, 0, 1);
}

// OpenGL initialization
void init(void) {
        colorcube();
        // Load shaders and use the resulting shader program
        GLuint program = InitShader("vshader36.glsl", "fshader36.glsl");
        glUseProgram(program);

        // Create a vertex array object
        GLuint vao;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);

        // Create and initialize a buffer object
        GLuint buffer;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors), NULL, GL_STATIC_DRAW);

        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
        glBufferSubData(GL_ARRAY_BUFFER, sizeof(points),  sizeof(colors), colors);

        // set up vertex arrays
        glEnableVertexAttribArray(0);
        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

        model = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, -5.0));

        glEnableVertexAttribArray(1);
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points)));

        mvpUniform = glGetUniformLocation(program, "mvp");
        glEnable(GL_DEPTH_TEST);
        glClearColor(1.0, 1.0, 1.0, 1.0);
}

void trackball_ptov(int x, int y, int width, int height, float v[3]) {
        float d, a;
        /* project x, y onto a hemisphere centered within width, height , note z is up here*/
        v[0] = (2.0*x - width) / width;
        v[1] = (height - 2.0F*y) / height;
        d = sqrt(v[0]*v[0] + v[1]*v[1]);
        v[2] = cos((M_PI/2.0) * ((d < 1.0) ? d : 1.0));
        a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
        v[0] *= a;
        v[1] *= a;
        v[2] *= a;
}

void display() {
 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 glm::mat4 proj = glm::perspective(90.F, 1.F, 0.1F, 100.F);

 glm::mat4 view = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, 0.0)); //apply mouse translation
 //view = glm::rotate(view, 0.2*mousediff.x, glm::vec3(0.0, 1.0, 0.0)); //apply mouse rotation
 //view = glm::rotate(view, 0.2*mousediff.y, glm::vec3(1.0, 0.0, 0.0));

//model = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, -5.0));


 //glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(proj));
 glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(proj*view*model));
 //glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(model*view*proj));

 glDrawArrays(GL_TRIANGLES, 0, NumVertices);
 glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y) {
        switch(key) {
                case 033: // Escape Key
                case 'q': case 'Q':
                        exit(EXIT_SUCCESS);
                        break;
        }
}

void mouseButton(int button, int state, int x, int y) {
        if(button==GLUT_RIGHT_BUTTON) exit(0);
        /* holding down left button allows user to rotate cube */
        if(button==GLUT_LEFT_BUTTON)
                switch(state) {
                        case GLUT_DOWN:
                                        trackingMouse = true;
                                        startX = x;
                                        startY = y;
                                        curx = x;
                                        cury = y;
                                        trackball_ptov(x, y, 512, 512, lastPos);
                                        break;
                        case GLUT_UP:
                                        trackingMouse = false;
                                        angle = 0.0;
                                        break;
                }
}

void mouseMotion(int x, int y) {
        float curPos[3], dx, dy, dz;
        /* compute position on hemisphere */

        if(trackingMouse) {
                /* compute the change in position on the hemisphere */
                trackball_ptov(x, y, 512, 512, curPos);

                dx = curPos[0] - lastPos[0];                
                dy = curPos[1] - lastPos[1];
                dz = curPos[2] - lastPos[2];
                if (dx || dy || dz) {
                        /* compute theta and cross product */
                        angle = 90.0 * sqrt(dx*dx + dy*dy + dz*dz);
                        axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
                        axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
                        axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
                        /* update position */
                        lastPos[0] = curPos[0];
                        lastPos[1] = curPos[1];
                        lastPos[2] = curPos[2];
                }
                float w = angle;
                float x = axis[0];
                float y = axis[1];
                float z = axis[2];
                glm::mat4 xform = glm::mat4((1.F - (2.F * ( y*y + z*z ))),(2.F * ( x*y - z*w )),( x*z + y*w ),0.F,
                (2.F * ( x*y + z*w )),(1.F - (2.F * ( x*x + z*z ))),(2.F * ( y*z - x*w )),0.F,
                (2.F * ( x*z - y*w )),(2.F * ( y*z + x*w )),(1.F - (2.F * ( x*x + y*y ))),0.F,
                0.F,0.F,0.F,1.F);

                model = xform*model;
        }
        glutPostRedisplay();
}


int main(int argc, char **argv) {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
        glutInitWindowSize(512, 512);
        glutCreateWindow("Color Cube");
        glewInit();
        init();
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutIdleFunc(display);
        glutMouseFunc(mouseButton);
        glutMotionFunc(mouseMotion);
        glutMainLoop();
        return 0;
}

这是fshader36

     #version 150
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}

这里是VSHADER

#version 330
uniform mat4 mvp;
layout(location=0) in vec4 vPosition;
layout(location=1) in vec4 vColor;
out vec4 color;

void main() {
    color = vColor;
    gl_Position = mvp * vPosition;
}

0 个答案:

没有答案