OpenGL轨迹球代码

转自:http://blog.sina.com.cn/s/blog_8d8425f30100ywap.html

从网上下载的经典OpenGL轨迹球代码,自己增加了缩放操作,共三个文件:

sam从网上下载的经典OpenGL轨迹球代码,自己增加了缩放操作,共三个文件:
sample.cpp ArcBall.cpp ArcBall.h

///sample.cpp

#pragma comment( lib, "opengl32.lib" )                
#pragma comment( lib, "glut32.lib")
#pragma comment( lib, "glew32.lib")                    
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <math.h>                                                
#include "ArcBall.h"                                                                                                                            

//初始化,必须用全局变量的方式,不能用new
ArcBallT arcBall(600.0f,400.0f);
ArcBallT*    ArcBall =&arcBall;// new ArcBallT(600.0f,400.0f);//&arcBall;

void reshape(int w, int h){
    glViewport(0,0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1, 1, -1, 1, 1.5, 20);
    glMatrixMode(GL_MODELVIEW);
    ball
    ArcBall->setBounds((GLfloat)w, (GLfloat)h);//1. 设置窗口边界
}
void init(){
    glClearColor(0,0,0,0);
    glShadeModel(GL_FLAT);
}

void display (void)
{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);               
    glColor3f(1.0,1.0,1.0);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0,
        0.0, 0.0, 0.0,
        0.0, 1.0, 0.0);
    glScalef(1.0, 2.0, 1.0);

    //glPushMatrix();                
    glTranslatef(0,0,-3);            
    glScalef(ArcBall->zoomRate, ArcBall->zoomRate, ArcBall->zoomRate);//2. 缩放
    glMultMatrixf(ArcBall->Transform.M);                        //3. 旋转
    glutWireCube(1.0);
    //glPopMatrix();                                                    

    glFlush ();                                                        
}
//移动
void move(int x, int y)                         
{
    ArcBall->MousePt.s.X = x;
    ArcBall->MousePt.s.Y = y;
    ArcBall->upstate();
    glutPostRedisplay();
}
//点击
void mouse(int button, int state, int x, int y) 
{
    if(button == GLUT_LEFT_BUTTON && state==GLUT_DOWN){
        ArcBall->isClicked = true;
        move(x,y);
    }
    else if(button == GLUT_LEFT_BUTTON && state==GLUT_UP)
        ArcBall->isClicked = false;
    else if(button == GLUT_RIGHT_BUTTON && state==GLUT_DOWN){
        ArcBall->isRClicked = true;
        move(x,y);
    }
    else if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
        ArcBall->isRClicked = false;
    ArcBall->upstate();
    glutPostRedisplay();
}
int main(int argc, char** argv){
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    glutInitWindowSize(640,480);
    glutCreateWindow("HI");

    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    glutMouseFunc(mouse);        //registered the mouse event.
    glutMotionFunc(move);        //registered the move event

    glutMainLoop();

    return 0;
}

///ArcBall.cpp

//#include <windows.h>                                
#include <GL/glew.h>        

#include <math.h>                                    
#include "ArcBall.h"                                 

//轨迹球参数:
//直径                    2.0f
//半径                    1.0f
//半径平方                1.0f


void ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const
{
    Point2fT TempPt;
    GLfloat length;

    //复制到临时变量
    TempPt = *NewPt;

    //把长宽调整到[-1 ... 1]区间
    TempPt.s.X  =        (TempPt.s.X * this->AdjustWidth)  - 1.0f;
    TempPt.s.Y  = 1.0f - (TempPt.s.Y * this->AdjustHeight);

    //计算长度的平方
    length      = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);

    //如果点映射到球的外面
    if (length > 1.0f)
    {
        GLfloat norm;

        //缩放到球上
        norm    = 1.0f / FuncSqrt(length);

        //设置z坐标为0
        NewVec->s.X = TempPt.s.X * norm;
        NewVec->s.Y = TempPt.s.Y * norm;
        NewVec->s.Z = 0.0f;
    }
    //如果在球内
    else   
    {
        //利用半径的平方为1,求出z坐标
        NewVec->s.X = TempPt.s.X;
        NewVec->s.Y = TempPt.s.Y;
        NewVec->s.Z = FuncSqrt(1.0f - length);
    }
}

ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)
{
    this->StVec.s.X     =0.0f;
    this->StVec.s.Y     = 0.0f;
    this->StVec.s.Z     = 0.0f;

    this->EnVec.s.X     =0.0f;
    this->EnVec.s.Y     = 0.0f;
    this->EnVec.s.Z     = 0.0f;


    Matrix4fSetIdentity(&Transform);
    Matrix3fSetIdentity(&LastRot);
    Matrix3fSetIdentity(&ThisRot);

    this->isDragging=false;
    this->isClicked= false;
    this->isRClicked = false;
    this->isZooming = false;
    this->zoomRate = 1;
    this->setBounds(NewWidth, NewHeight);
}

void ArcBall_t::upstate()
{
    if(!this->isZooming && this->isRClicked){                    // 开始拖动
        this->isZooming = true;                                        // 设置拖动为变量为true        
        this->LastPt = this->MousePt;
        this->lastZoomRate = this->zoomRate;
    }
    else if(this->isZooming){//正在拖动
        if(this->isRClicked){                //拖动        
            Point2fSub(&this->MousePt, &this->LastPt);
            this->zoomRate = this->lastZoomRate + this->MousePt.s.X * this->AdjustWidth * 2;
        }
        else{                                            //停止拖动
            this->isZooming = false;
        }
    }
    else if (!this->isDragging && this->isClicked){                                               // 如果没有拖动
        this->isDragging = true;                                        // 设置拖动为变量为true
        this->LastRot = this->ThisRot;                                        
        this->click(&this->MousePt);                                
    }
    else if(this->isDragging){
        if (this->isClicked){                                            //如果按住拖动
            Quat4fT     ThisQuat;

            this->drag(&this->MousePt, &ThisQuat);                        // 更新轨迹球的变量
            Matrix3fSetRotationFromQuat4f(&this->ThisRot, &ThisQuat);       // 计算旋转量
            Matrix3fMulMatrix3f(&this->ThisRot, &this->LastRot);                
            Matrix4fSetRotationFromMatrix3f(&this->Transform, &this->ThisRot);    
        }
        else                                                        // 如果放开鼠标,设置拖动为false
            this->isDragging = false;
    }
}

//按下鼠标,记录当前对应的轨迹球的位置
void    ArcBall_t::click(const Point2fT* NewPt)
{
    this->_mapToSphere(NewPt, &this->StVec);
}

//鼠标拖动,计算旋转四元数
void    ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)
{
    //新的位置
    this->_mapToSphere(NewPt, &this->EnVec);

    //计算旋转
    if (NewRot)
    {
        Vector3fT  Perp;

        //计算旋转轴
        Vector3fCross(&Perp, &this->StVec, &this->EnVec);

        //如果不为0
        if (Vector3fLength(&Perp) > Epsilon)    
        {
            //记录旋转轴
            NewRot->s.X = Perp.s.X;
            NewRot->s.Y = Perp.s.Y;
            NewRot->s.Z = Perp.s.Z;
            //在四元数中,w=cos(a/2),a为旋转的角度
            NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec);
        }
        //是0,说明没有旋转
        else                                 
        {
            NewRot->s.X = 
                NewRot->s.Y = 
                NewRot->s.Z = 
                NewRot->s.W = 0.0f;
        }
    }
}



///ArcBall.h///

#ifndef _ArcBall_h
#define _ArcBall_h

#include <stdlib.h>

// 仅在Debug模式下,启用断言
#ifdef _DEBUG
# include "assert.h"
#else
# define assert(x) { }
#endif


//2维点
typedef union Tuple2f_t
{
    struct
    {
        GLfloat X, Y;
    } s;

    GLfloat T[2];
} Tuple2fT;     

//3维点
typedef union Tuple3f_t
{
    struct
    {
        GLfloat X, Y, Z;
    } s;

    GLfloat T[3];
} Tuple3fT;      

//4维点
typedef union Tuple4f_t
{
    struct
    {
        GLfloat X, Y, Z, W;
    } s;

    GLfloat T[4];
} Tuple4fT;      


//3x3矩阵
typedef union Matrix3f_t
{
    struct
    {
        //column major
        union { GLfloat M00; GLfloat XX; GLfloat SX; };  
        union { GLfloat M10; GLfloat XY;             };  
        union { GLfloat M20; GLfloat XZ;             };  
        union { GLfloat M01; GLfloat YX;             };  
        union { GLfloat M11; GLfloat YY; GLfloat SY; };  
        union { GLfloat M21; GLfloat YZ;             };  
        union { GLfloat M02; GLfloat ZX;             };  
        union { GLfloat M12; GLfloat ZY;             };  
        union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };  
    } s;
    GLfloat M[9];
} Matrix3fT;    

//4x4矩阵
typedef union Matrix4f_t
{
    struct
    {
        //column major
        union { GLfloat M00; GLfloat XX; GLfloat SX; };  
        union { GLfloat M10; GLfloat XY;             };  
        union { GLfloat M20; GLfloat XZ;             };  
        union { GLfloat M30; GLfloat XW;             };  
        union { GLfloat M01; GLfloat YX;             };  
        union { GLfloat M11; GLfloat YY; GLfloat SY; };  
        union { GLfloat M21; GLfloat YZ;             };  
        union { GLfloat M31; GLfloat YW;             };  
        union { GLfloat M02; GLfloat ZX;             };  
        union { GLfloat M12; GLfloat ZY;             };  
        union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };  
        union { GLfloat M32; GLfloat ZW;             };  
        union { GLfloat M03; GLfloat TX;             };  
        union { GLfloat M13; GLfloat TY;             };  
        union { GLfloat M23; GLfloat TZ;             };  
        union { GLfloat M33; GLfloat TW; GLfloat SW; };  
    } s;
    GLfloat M[16];
} Matrix4fT;    


//定义类型的别名
#define Point2fT    Tuple2fT   
#define Quat4fT     Tuple4fT   
#define Vector2fT   Tuple2fT   
#define Vector3fT   Tuple3fT   
#define FuncSqrt    sqrtf
# define Epsilon 1.0e-5

//2维点相加
inline
static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1)
{
    assert(NewObj && t1);

    NewObj->s.X += t1->s.X;
    NewObj->s.Y += t1->s.Y;
}

//2维点相减
inline
static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1)
{
    assert(NewObj && t1);

    NewObj->s.X -= t1->s.X;
    NewObj->s.Y -= t1->s.Y;
}

//3维点矢积
inline
static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2)
{
    Vector3fT Result; 

    assert(NewObj && v1 && v2);

    Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y);
    Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z);
    Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X);

    *NewObj = Result;
}

//3维点点积
inline
static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1)
{
    assert(NewObj && v1);

    return  (NewObj->s.X * v1->s.X) +
        (NewObj->s.Y * v1->s.Y) +
        (NewObj->s.Z * v1->s.Z);
}

//3维点的长度的平方
inline
static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj)
{
    assert(NewObj);

    return  (NewObj->s.X * NewObj->s.X) +
        (NewObj->s.Y * NewObj->s.Y) +
        (NewObj->s.Z * NewObj->s.Z);
}

//3维点的长度
inline
static GLfloat Vector3fLength(const Vector3fT* NewObj)
{
    assert(NewObj);

    return FuncSqrt(Vector3fLengthSquared(NewObj));
}

//设置3x3矩阵为0矩阵
inline
static void Matrix3fSetZero(Matrix3fT* NewObj)
{
    NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 
        NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 
        NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;
}

//设置4x4矩阵为0矩阵
inline
static void Matrix4fSetZero(Matrix4fT* NewObj)
{
    NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 
        NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 
        NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 
        NewObj->s.M30 = NewObj->s.M31 = NewObj->s.M32 = 0.0f;
}

//设置3x3矩阵为单位矩阵
inline
static void Matrix3fSetIdentity(Matrix3fT* NewObj)
{
    Matrix3fSetZero(NewObj);

    NewObj->s.M00 = 
        NewObj->s.M11 = 
        NewObj->s.M22 = 1.0f;
}

//设置4x4矩阵为单位矩阵
inline
static void Matrix4fSetIdentity(Matrix4fT* NewObj)
{
    Matrix4fSetZero(NewObj);

    NewObj->s.M00 = 1.0f;
    NewObj->s.M11 = 1.0f;
    NewObj->s.M22 = 1.0f;
    NewObj->s.M33=1.0f;
}

//从四元数设置旋转矩阵
inline
static void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1)
{
    GLfloat n, s;
    GLfloat xs, ys, zs;
    GLfloat wx, wy, wz;
    GLfloat xx, xy, xz;
    GLfloat yy, yz, zz;

    assert(NewObj && q1);

    n = (q1->s.X * q1->s.X) + (q1->s.Y * q1->s.Y) + (q1->s.Z * q1->s.Z) + (q1->s.W * q1->s.W);
    s = (n > 0.0f) ? (2.0f / n) : 0.0f;

    xs = q1->s.X * s;  ys = q1->s.Y * s;  zs = q1->s.Z * s;
    wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs;
    xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs;
    yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs;

    NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX =         xy - wz; NewObj->s.ZX =         xz + wy;
    NewObj->s.XY =         xy + wz;  NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY =         yz - wx;
    NewObj->s.XZ =         xz - wy;  NewObj->s.YZ =         yz + wx;  NewObj->s.ZZ = 1.0f - (xx + yy);
}

//3x3矩阵相乘
inline
static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1)
{
    Matrix3fT Result; 

    assert(NewObj && m1);

    Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20);
    Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21);
    Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22);

    Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20);
    Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21);
    Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22);

    Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20);
    Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21);
    Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22);

    *NewObj = Result;
}

//4x4矩阵相乘
inline
static void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1)
{
    assert(NewObj && m1);

    NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
    NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
    NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
}

//进行矩阵的奇异值分解,旋转矩阵被保存到rot3和rot4中,返回矩阵的缩放因子
inline
static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4)
{
    GLfloat s, n;

    assert(NewObj);

    s = FuncSqrt(
        ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + 
        (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +
        (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f );

    if (rot3)   
    {
        rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ;
        rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ;
        rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ;

        n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
            (NewObj->s.XY * NewObj->s.XY) +
            (NewObj->s.XZ * NewObj->s.XZ) );
        rot3->s.XX *= n;
        rot3->s.XY *= n;
        rot3->s.XZ *= n;

        n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
            (NewObj->s.YY * NewObj->s.YY) +
            (NewObj->s.YZ * NewObj->s.YZ) );
        rot3->s.YX *= n;
        rot3->s.YY *= n;
        rot3->s.YZ *= n;

        n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
            (NewObj->s.ZY * NewObj->s.ZY) +
            (NewObj->s.ZZ * NewObj->s.ZZ) );
        rot3->s.ZX *= n;
        rot3->s.ZY *= n;
        rot3->s.ZZ *= n;
    }

    if (rot4)  
    {
        if (rot4 != NewObj)
        {
            Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj); 
        }


        n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
            (NewObj->s.XY * NewObj->s.XY) +
            (NewObj->s.XZ * NewObj->s.XZ) );
        rot4->s.XX *= n;
        rot4->s.XY *= n;
        rot4->s.XZ *= n;

        n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
            (NewObj->s.YY * NewObj->s.YY) +
            (NewObj->s.YZ * NewObj->s.YZ) );
        rot4->s.YX *= n;
        rot4->s.YY *= n;
        rot4->s.YZ *= n;

        n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
            (NewObj->s.ZY * NewObj->s.ZY) +
            (NewObj->s.ZZ * NewObj->s.ZZ) );
        rot4->s.ZX *= n;
        rot4->s.ZY *= n;
        rot4->s.ZZ *= n;
    }

    return s;
}

//从3x3矩阵变为4x4的旋转矩阵
inline
static void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
{
    assert(NewObj && m1);

    NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
    NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
    NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
}

//4x4矩阵的与标量的乘积
inline
static void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale)
{
    assert(NewObj);

    NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale;
    NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale;
    NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;
}

//设置旋转矩阵
inline
static void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
{
    GLfloat scale;

    assert(NewObj && m1);

    scale = Matrix4fSVD(NewObj, NULL, NULL);

    Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1);
    Matrix4fMulRotationScale(NewObj, scale);
}



typedef class ArcBall_t
{
protected:
    //把二维点映射到三维点
    inline
        void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;

public:
    //构造/析构函数
    ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);
    ~ArcBall_t() { };

    //设置边界
    inline
        void    setBounds(GLfloat NewWidth, GLfloat NewHeight)
    {
        assert((NewWidth > 1.0f) && (NewHeight > 1.0f));

        //设置长宽的调整因子
        this->AdjustWidth  = 1.0f / ((NewWidth  - 1.0f) * 0.5f);
        this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
    }

    //鼠标点击
    void    click(const Point2fT* NewPt);

    //鼠标拖动计算旋转
    void    drag(const Point2fT* NewPt, Quat4fT* NewRot);

    //更新鼠标状态
    void    upstate();
    //void    mousemove(WPARAM wParam,LPARAM lParam);

protected:
    Vector3fT   StVec;          //保存鼠标点击的坐标
    Vector3fT   EnVec;          //保存鼠标拖动的坐标
    GLfloat     AdjustWidth;    //宽度的调整因子
    GLfloat     AdjustHeight;   //长度的调整因子
public:
    Matrix4fT   Transform;      //计算变换            
    Matrix3fT   LastRot;        //上一次的旋转 
    Matrix3fT   ThisRot;        //这次的旋转
    float zoomRate;
    float lastZoomRate;

    bool        isDragging;     // 是否拖动
    bool        isRClicked;     // 是否右击鼠标
    bool        isClicked;      // 是否点击鼠标
    bool        isZooming;    //是否正在缩放
    Point2fT    LastPt;        
    Matrix4fT origTransform;
    Point2fT    MousePt;        // 当前的鼠标位置

} ArcBallT;

#endifple.cpp ArcBall.cpp ArcBall.h


///sample.cpp

#pragma comment( lib, "opengl32.lib" )                            
#pragma comment( lib, "glut32.lib")
#pragma comment( lib, "glew32.lib")                                   
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glu.h>
#include <math.h>                                                                                    
#include "ArcBall.h"                                                                                                                                                                                                                         

//初始化,必须用全局变量的方式,不能用new
ArcBallT arcBall(600.0f,400.0f);
ArcBallT*       ArcBall =&arcBall;// new ArcBallT(600.0f,400.0f);//&arcBall;

void reshape(int w, int h){
       glViewport(0,0, w, h);
       glMatrixMode(GL_PROJECTION);
       glLoadIdentity();
       glFrustum(-1, 1, -1, 1, 1.5, 20);
       glMatrixMode(GL_MODELVIEW);
       ball
       ArcBall->setBounds((GLfloat)w, (GLfloat)h);//1. 设置窗口边界
}
void init(){
       glClearColor(0,0,0,0);
       glShadeModel(GL_FLAT);
}

void display (void)
{

       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);                           
       glColor3f(1.0,1.0,1.0);
       glLoadIdentity();
       gluLookAt(0.0, 0.0, 5.0,
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
       glScalef(1.0, 2.0, 1.0);

       //glPushMatrix();                            
       glTranslatef(0,0,-3);                     
       glScalef(ArcBall->zoomRate, ArcBall->zoomRate, ArcBall->zoomRate);//2. 缩放
       glMultMatrixf(ArcBall->Transform.M);                                          //3. 旋转
       glutWireCube(1.0);
       //glPopMatrix();                                                                                           

       glFlush ();                                                                                                  
}
//移动
void move(int x, int y)                                                 
{
       ArcBall->MousePt.s.X = x;
       ArcBall->MousePt.s.Y = y;
       ArcBall->upstate();
       glutPostRedisplay();
}
//点击
void mouse(int button, int state, int x, int y) 
{
       if(button == GLUT_LEFT_BUTTON && state==GLUT_DOWN){
              ArcBall->isClicked = true;
              move(x,y);
       }
       else if(button == GLUT_LEFT_BUTTON && state==GLUT_UP)
              ArcBall->isClicked = false;
       else if(button == GLUT_RIGHT_BUTTON && state==GLUT_DOWN){
              ArcBall->isRClicked = true;
              move(x,y);
       }
       else if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
              ArcBall->isRClicked = false;
       ArcBall->upstate();
       glutPostRedisplay();
}
int main(int argc, char** argv){
       glutInit(&argc, argv);
       glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
       glutInitWindowSize(640,480);
       glutCreateWindow("HI");

       init();
       glutDisplayFunc(display);
       glutReshapeFunc(reshape);

       glutMouseFunc(mouse);              //registered the mouse event.
       glutMotionFunc(move);              //registered the move event

       glutMainLoop();

       return 0;
}

///ArcBall.cpp

//#include <windows.h>                                                        
#include <GL/glew.h>              

#include <math.h>                                                                       
#include "ArcBall.h"                                                                 

//轨迹球参数:
//直径                                   2.0f
//半径                                   1.0f
//半径平方                            1.0f


void ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const
{
       Point2fT TempPt;
       GLfloat length;

       //复制到临时变量
       TempPt = *NewPt;

       //把长宽调整到[-1 ... 1]区间
       TempPt.s.X   =               (TempPt.s.X * this->AdjustWidth)   - 1.0f;
       TempPt.s.Y   = 1.0f - (TempPt.s.Y * this->AdjustHeight);

       //计算长度的平方
       length           = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);

       //如果点映射到球的外面
       if (length > 1.0f)
       {
              GLfloat norm;

              //缩放到球上
              norm       = 1.0f / FuncSqrt(length);

              //设置z坐标为0
              NewVec->s.X = TempPt.s.X * norm;
              NewVec->s.Y = TempPt.s.Y * norm;
              NewVec->s.Z = 0.0f;
       }
       //如果在球内
       else     
       {
              //利用半径的平方为1,求出z坐标
              NewVec->s.X = TempPt.s.X;
              NewVec->s.Y = TempPt.s.Y;
              NewVec->s.Z = FuncSqrt(1.0f - length);
       }
}

ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)
{
       this->StVec.s.X         =0.0f;
       this->StVec.s.Y         = 0.0f;
       this->StVec.s.Z         = 0.0f;

       this->EnVec.s.X         =0.0f;
       this->EnVec.s.Y         = 0.0f;
       this->EnVec.s.Z         = 0.0f;


       Matrix4fSetIdentity(&Transform);
       Matrix3fSetIdentity(&LastRot);
       Matrix3fSetIdentity(&ThisRot);

       this->isDragging=false;
       this->isClicked= false;
       this->isRClicked = false;
       this->isZooming = false;
       this->zoomRate = 1;
       this->setBounds(NewWidth, NewHeight);
}

void ArcBall_t::upstate()
{
       if(!this->isZooming && this->isRClicked){                                   // 开始拖动
              this->isZooming = true;                                                                      // 设置拖动为变量为true              
              this->LastPt = this->MousePt;
              this->lastZoomRate = this->zoomRate;
       }
       else if(this->isZooming){//正在拖动
              if(this->isRClicked){                            //拖动              
                     Point2fSub(&this->MousePt, &this->LastPt);
                     this->zoomRate = this->lastZoomRate + this->MousePt.s.X * this->AdjustWidth * 2;
              }
              else{                                                                             //停止拖动
                     this->isZooming = false;
              }
       }
       else if (!this->isDragging && this->isClicked){                                                                                   // 如果没有拖动
              this->isDragging = true;                                                                      // 设置拖动为变量为true
              this->LastRot = this->ThisRot;                                                                      
              this->click(&this->MousePt);                                                        
       }
       else if(this->isDragging){
              if (this->isClicked){                                                                             //如果按住拖动
                     Quat4fT         ThisQuat;

                     this->drag(&this->MousePt, &ThisQuat);                                          // 更新轨迹球的变量
                     Matrix3fSetRotationFromQ uat4f(&this->ThisRot, &ThisQuat);             // 计算旋转量
                     Matrix3fMulMatrix3f(&this->ThisRot, &this->LastRot);                            
                     Matrix4fSetRotationFromM atrix3f(&this->Transform, &this->ThisRot);       
              }
              else                                                                                                  // 如果放开鼠标,设置拖动为false
                     this->isDragging = false;
       }
}

//按下鼠标,记录当前对应的轨迹球的位置
void       ArcBall_t::click(const Point2fT* NewPt)
{
       this->_mapToSphere(NewPt, &this->StVec);
}

//鼠标拖动,计算旋转四元数
void       ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)
{
       //新的位置
       this->_mapToSphere(NewPt, &this->EnVec);

       //计算旋转
       if (NewRot)
       {
              Vector3fT   Perp;

              //计算旋转轴
              Vector3fCross(&Perp, &this->StVec, &this->EnVec);

              //如果不为0
              if (Vector3fLength(&Perp) > Epsilon)       
              {
                     //记录旋转轴
                     NewRot->s.X = Perp.s.X;
                     NewRot->s.Y = Perp.s.Y;
                     NewRot->s.Z = Perp.s.Z;
                     //在四元数中,w=cos(a/2),a为旋转的角度
                     NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec);
              }
              //是0,说明没有旋转
              else                                                                 
              {
                     NewRot->s.X = 
                            NewRot->s.Y = 
                            NewRot->s.Z = 
                            NewRot->s.W = 0.0f;
              }
       }
}



///ArcBall.h///

#ifndef _ArcBall_h
#define _ArcBall_h

#include <stdlib.h>

// 仅在Debug模式下,启用断言
#ifdef _DEBUG
# include "assert.h"
#else
# define assert(x) { }
#endif


//2维点
typedef union Tuple2f_t
{
       struct
       {
              GLfloat X, Y;
       } s;

       GLfloat T[2];
} Tuple2fT;         

//3维点
typedef union Tuple3f_t
{
       struct
       {
              GLfloat X, Y, Z;
       } s;

       GLfloat T[3];
} Tuple3fT;           

//4维点
typedef union Tuple4f_t
{
       struct
       {
              GLfloat X, Y, Z, W;
       } s;

       GLfloat T[4];
} Tuple4fT;           


//3x3矩阵
typedef union Matrix3f_t
{
       struct
       {
              //column major
              union { GLfloat M00; GLfloat XX; GLfloat SX; };   
              union { GLfloat M10; GLfloat XY;                         };   
              union { GLfloat M20; GLfloat XZ;                         };   
              union { GLfloat M01; GLfloat YX;                         };   
              union { GLfloat M11; GLfloat YY; GLfloat SY; };   
              union { GLfloat M21; GLfloat YZ;                         };   
              union { GLfloat M02; GLfloat ZX;                         };   
              union { GLfloat M12; GLfloat ZY;                         };   
              union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };   
       } s;
       GLfloat M[9];
} Matrix3fT;       

//4x4矩阵
typedef union Matrix4f_t
{
       struct
       {
              //column major
              union { GLfloat M00; GLfloat XX; GLfloat SX; };   
              union { GLfloat M10; GLfloat XY;                         };   
              union { GLfloat M20; GLfloat XZ;                         };   
              union { GLfloat M30; GLfloat XW;                         };   
              union { GLfloat M01; GLfloat YX;                         };   
              union { GLfloat M11; GLfloat YY; GLfloat SY; };   
              union { GLfloat M21; GLfloat YZ;                         };   
              union { GLfloat M31; GLfloat YW;                         };   
              union { GLfloat M02; GLfloat ZX;                         };   
              union { GLfloat M12; GLfloat ZY;                         };   
              union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };   
              union { GLfloat M32; GLfloat ZW;                         };   
              union { GLfloat M03; GLfloat TX;                         };   
              union { GLfloat M13; GLfloat TY;                         };   
              union { GLfloat M23; GLfloat TZ;                         };   
              union { GLfloat M33; GLfloat TW; GLfloat SW; };   
       } s;
       GLfloat M[16];
} Matrix4fT;       


//定义类型的别名
#define Point2fT       Tuple2fT     
#define Quat4fT         Tuple4fT     
#define Vector2fT     Tuple2fT     
#define Vector3fT     Tuple3fT     
#define FuncSqrt       sqrtf
# define Epsilon 1.0e-5

//2维点相加
inline
static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1)
{
       assert(NewObj && t1);

       NewObj->s.X += t1->s.X;
       NewObj->s.Y += t1->s.Y;
}

//2维点相减
inline
static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1)
{
       assert(NewObj && t1);

       NewObj->s.X -= t1->s.X;
       NewObj->s.Y -= t1->s.Y;
}

//3维点矢积
inline
static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2)
{
       Vector3fT Result; 

       assert(NewObj && v1 && v2);

       Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y);
       Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z);
       Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X);

       *NewObj = Result;
}

//3维点点积
inline
static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1)
{
       assert(NewObj && v1);

       return   (NewObj->s.X * v1->s.X) +
              (NewObj->s.Y * v1->s.Y) +
              (NewObj->s.Z * v1->s.Z);
}

//3维点的长度的平方
inline
static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj)
{
       assert(NewObj);

       return   (NewObj->s.X * NewObj->s.X) +
              (NewObj->s.Y * NewObj->s.Y) +
              (NewObj->s.Z * NewObj->s.Z);
}

//3维点的长度
inline
static GLfloat Vector3fLength(const Vector3fT* NewObj)
{
       assert(NewObj);

       return FuncSqrt(Vector3fLengthSquared(NewObj));
}

//设置3x3矩阵为0矩阵
inline
static void Matrix3fSetZero(Matrix3fT* NewObj)
{
       NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 
              NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 
              NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;
}

//设置4x4矩阵为0矩阵
inline
static void Matrix4fSetZero(Matrix4fT* NewObj)
{
       NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = 
              NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = 
              NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 
              NewObj->s.M30 = NewObj->s.M31 = NewObj->s.M32 = 0.0f;
}

//设置3x3矩阵为单位矩阵
inline
static void Matrix3fSetIdentity(Matrix3fT* NewObj)
{
       Matrix3fSetZero(NewObj);

       NewObj->s.M00 = 
              NewObj->s.M11 = 
              NewObj->s.M22 = 1.0f;
}

//设置4x4矩阵为单位矩阵
inline
static void Matrix4fSetIdentity(Matrix4fT* NewObj)
{
       Matrix4fSetZero(NewObj);

       NewObj->s.M00 = 1.0f;
       NewObj->s.M11 = 1.0f;
       NewObj->s.M22 = 1.0f;
       NewObj->s.M33=1.0f;
}

//从四元数设置旋转矩阵
inline
static void Matrix3fSetRotationFromQ uat4f(Matrix3fT* NewObj, const Quat4fT* q1)
{
       GLfloat n, s;
       GLfloat xs, ys, zs;
       GLfloat wx, wy, wz;
       GLfloat xx, xy, xz;
       GLfloat yy, yz, zz;

       assert(NewObj && q1);

       n = (q1->s.X * q1->s.X) + (q1->s.Y * q1->s.Y) + (q1->s.Z * q1->s.Z) + (q1->s.W * q1->s.W);
       s = (n > 0.0f) ? (2.0f / n) : 0.0f;

       xs = q1->s.X * s;   ys = q1->s.Y * s;   zs = q1->s.Z * s;
       wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs;
       xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs;
       yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs;

       NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX =                 xy - wz;  NewObj->s.ZX =                 xz + wy;
       NewObj->s.XY =                 xy + wz;   NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY =                 yz - wx;
       NewObj->s.XZ =                 xz - wy;   NewObj->s.YZ =                 yz + wx;   NewObj->s.ZZ = 1.0f - (xx + yy);
}

//3x3矩阵相乘
inline
static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1)
{
       Matrix3fT Result; 

       assert(NewObj && m1);

       Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20);
       Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21);
       Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22);

       Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20);
       Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21);
       Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22);

       Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20);
       Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21);
       Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22);

       *NewObj = Result;
}

//4x4矩阵相乘
inline
static void Matrix4fSetRotationScale FromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1)
{
       assert(NewObj && m1);

       NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
       NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
       NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
}

//进行矩阵的奇异值分解,旋转矩阵被保存到rot3和rot4中,返回矩阵的缩放因子
inline
static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4)
{
       GLfloat s, n;

       assert(NewObj);

       s = FuncSqrt(
              ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + 
              (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +
              (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f );

       if (rot3)     
       {
              rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ;
              rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ;
              rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ;

              n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
                     (NewObj->s.XY * NewObj->s.XY) +
                     (NewObj->s.XZ * NewObj->s.XZ) );
              rot3->s.XX *= n;
              rot3->s.XY *= n;
              rot3->s.XZ *= n;

              n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
                     (NewObj->s.YY * NewObj->s.YY) +
                     (NewObj->s.YZ * NewObj->s.YZ) );
              rot3->s.YX *= n;
              rot3->s.YY *= n;
              rot3->s.YZ *= n;

              n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
                     (NewObj->s.ZY * NewObj->s.ZY) +
                     (NewObj->s.ZZ * NewObj->s.ZZ) );
              rot3->s.ZX *= n;
              rot3->s.ZY *= n;
              rot3->s.ZZ *= n;
       }

       if (rot4)   
       {
              if (rot4 != NewObj)
              {
                     Matrix4fSetRotationScale FromMatrix4f(rot4, NewObj); 
              }


              n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +
                     (NewObj->s.XY * NewObj->s.XY) +
                     (NewObj->s.XZ * NewObj->s.XZ) );
              rot4->s.XX *= n;
              rot4->s.XY *= n;
              rot4->s.XZ *= n;

              n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +
                     (NewObj->s.YY * NewObj->s.YY) +
                     (NewObj->s.YZ * NewObj->s.YZ) );
              rot4->s.YX *= n;
              rot4->s.YY *= n;
              rot4->s.YZ *= n;

              n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +
                     (NewObj->s.ZY * NewObj->s.ZY) +
                     (NewObj->s.ZZ * NewObj->s.ZZ) );
              rot4->s.ZX *= n;
              rot4->s.ZY *= n;
              rot4->s.ZZ *= n;
       }

       return s;
}

//从3x3矩阵变为4x4的旋转矩阵
inline
static void Matrix4fSetRotationScale FromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
{
       assert(NewObj && m1);

       NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;
       NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;
       NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;
}

//4x4矩阵的与标量的乘积
inline
static void Matrix4fMulRotationScale (Matrix4fT* NewObj, GLfloat scale)
{
       assert(NewObj);

       NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale;
       NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale;
       NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;
}

//设置旋转矩阵
inline
static void Matrix4fSetRotationFromM atrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)
{
       GLfloat scale;

       assert(NewObj && m1);

       scale = Matrix4fSVD(NewObj, NULL, NULL);

       Matrix4fSetRotationScale FromMatrix3f(NewObj, m1);
       Matrix4fMulRotationScale (NewObj, scale);
}



typedef class ArcBall_t
{
protected:
       //把二维点映射到三维点
       inline
              void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;

public:
       //构造/析构函数
       ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);
       ~ArcBall_t() { };

       //设置边界
       inline
              void       setBounds(GLfloat NewWidth, GLfloat NewHeight)
       {
              assert((NewWidth > 1.0f) && (NewHeight > 1.0f));

              //设置长宽的调整因子
              this->AdjustWidth   = 1.0f / ((NewWidth   - 1.0f) * 0.5f);
              this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);
       }

       //鼠标点击
       void       click(const Point2fT* NewPt);

       //鼠标拖动计算旋转
       void       drag(const Point2fT* NewPt, Quat4fT* NewRot);

       //更新鼠标状态
       void       upstate();
       //void       mousemove(WPARAM wParam,LPARAM lParam);

protected:
       Vector3fT     StVec;                   //保存鼠标点击的坐标
       Vector3fT     EnVec;                   //保存鼠标拖动的坐标
       GLfloat         AdjustWidth;       //宽度的调整因子
       GLfloat         AdjustHeight;     //长度的调整因子
public:
       Matrix4fT     Transform;           //计算变换                     
       Matrix3fT     LastRot;               //上一次的旋转 
       Matrix3fT     ThisRot;               //这次的旋转
       float zoomRate;
       float lastZoomRate;

       bool               isDragging;         // 是否拖动
       bool               isRClicked;         // 是否右击鼠标
       bool               isClicked;           // 是否点击鼠标
       bool               isZooming;       //是否正在缩放
       Point2fT       LastPt;              
       Matrix4fT origTransform;
       Point2fT       MousePt;               // 当前的鼠标位置

} ArcBallT;

#endif
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: OpenGL是一个图形库,轨迹球是一种常见的交互技术,用于实现对物体的旋转操作。而鼠标是常见的输入设备,可以用来控制轨迹球的旋转。 要实现鼠标旋转功能,我们可以按照以下步骤进行: 1. 首先,我们需要获取鼠标的输入。在OpenGL中,可以使用操作系统提供的API来获取鼠标坐标和鼠标按钮事件。 2. 接下来,我们需要将鼠标坐标转换为OpenGL坐标。鼠标的坐标范围是屏幕上的像素坐标,而OpenGL使用的是归一化坐标系。我们可以使用视口变换函数来进行转换。 3. 然后,我们需要将鼠标的移动量转换为物体的旋转量。可以根据鼠标在屏幕上的移动距离来计算旋转矩阵。一种常见的方法是使用四元数来表示旋转。 4. 最后,我们需要将旋转矩阵应用到物体上,在渲染时实现旋转效果。可以将旋转矩阵与物体的模型矩阵相乘,得到最终的变换矩阵。 使用轨迹球实现鼠标旋转功能可以提供良好的用户交互体验。它可以通过鼠标在屏幕上的移动来实现物体的旋转,而且操作简单直观。通过使用OpenGL轨迹球技术,我们可以轻松实现鼠标旋转功能,为用户提供更加灵活和自由的操作方式。 ### 回答2: OpenGL轨迹球是一种常用的技术,可以实现通过鼠标控制物体的旋转。具体实现步骤如下: 1. 初始化:创建OpenGL窗口,并将透视视图设置为合适的视角。 2. 定义视图变量:使用四元数来记录物体的旋转状态。初始状态下,视图变量为单位四元数。 3. 鼠标操作:根据鼠标的移动来计算旋转的角度。通过获取当前鼠标位置与上一帧鼠标位置的差值,可以计算出鼠标在屏幕上的平移方向。 4. 将鼠标平移方向转换为旋转方向:将鼠标在屏幕上的平移向量转换为场景中的旋转向量。可以通过将鼠标平移向量与视图矩阵的逆矩阵相乘来实现。 5. 计算旋转角度:使用三角函数,通过计算旋转向量的长度来获取旋转角度。 6. 更新视图变量:根据旋转角度和旋转向量,更新视图变量。可以将旋转向量乘以旋转角度,并与当前视图变量相乘。 7. 绘制场景:根据更新后的视图变量进行场景渲染,将旋转效果显示出来。 8. 循环操作:通过循环将上述步骤持续执行,实现实时的鼠标旋转效果。 通过以上步骤,可以实现用OpenGL轨迹球来实现鼠标旋转效果。该实现可以使用户更加直观地进行物体的旋转操作,提高交互体验。 ### 回答3: OpenGL 轨迹球实现鼠标旋转是一种常见的交互技术,在3D视图中允许用户通过鼠标拖动来旋转模型或场景。 首先,需要获取鼠标移动事件并将其转换为旋转角度。一种常见的方法是通过记录鼠标在屏幕上的位置差异来计算旋转角度的增量。例如,当鼠标向右移动时,模型应该顺时针旋转。因此,可以使用鼠标水平移动的数量来计算旋转角度的增量。 然后,需要将旋转角度应用于模型或场景。在OpenGL中,可以使用旋转矩阵来实现这一点。最简单的方法是通过glRotate函数来应用旋转矩阵。该函数接受旋转角度和旋转轴作为参数,并将其应用于当前模型视图矩阵中。例如,可以使用glRotatef函数来实现简单的旋转。 最后,需要在主循环中重绘场景以显示旋转效果。当鼠标移动时,需要重新计算旋转角度并重新绘制场景。通过将新的旋转角度应用于模型视图矩阵,然后重绘场景,可以实现平滑的旋转动画。 综上所述,使用OpenGL轨迹球实现鼠标旋转涉及获取鼠标移动事件,计算旋转角度,应用旋转角度到模型视图矩阵,以及重绘场景。这一技术可以增强用户交互性,并且在很多3D应用程序中得到广泛应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值