OpenGL glut OFF 读取 + 半边数据结构存储

3 篇文章 0 订阅
2 篇文章 1 订阅

文件格式:
https://people.sc.fsu.edu/~jburkardt/data/off/off.html
第一行:OFF
第二行:顶点数 面数 边数
接下来对于某一个顶点都有一行:x y z
接下来对于每一个多边形面都有一行:n v1 v2 … vn, 即 the number of vertices, and the vertex indices for each face.
(顶点的编号此时被隐含输入了,从0开始一直到n-1.)

以上如果要规定颜色:
对于每一个 colored vertex 都有一行:x y z r g b a
可以通过遵循顶点的XYZ坐标和RGBA颜色坐标来为顶点分配颜色(“ A”坐标控制透明度)。
对于每一个面都有一行:n v1 v2 … vn r g b a,
可以通过遵循顶点的XYZ坐标和RGBA颜色坐标来为顶点分配颜色(“ A”坐标控制透明度)。

Normally, color is not specified for BOTH the vertices and faces. If the node colors are specified, then the faces are colored with a smooth interpolation of the colors of their vertices.
如果指定了节点颜色,面的颜色将会被平滑插值。

函数解释
gluLookAt()
该 函数定义一个视图 矩阵,并与当前矩阵相乘。
第一组eyex, eyey,eyez 相机在世界坐标的位置
第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置
第三组upx,upy,upz 相机向上的方向在世界坐标中的方向
你把相机想象成为你自己的脑袋:
第一组数据就是脑袋的位置
第二组数据就是眼睛看的物体的位置
第三组就是头顶朝向的方向(因为你可以歪着头看同一个物体)。

半边结构:
http://www.cs.deas.harvard.edu/~xgu/mesh/

	存储:
    struct HE_edge {
        HE_vert* vert;   // vertex at the end of the half-edge
        HE_edge* pair;   // oppositely oriented adjacent half-edge 
        HE_face* face;   // face the half-edge borders
        HE_edge* next;   // next half-edge around the face
    
    };
	
	struct HE_vert {
        float x;
        float y;
        float z;

        HE_edge* edge;  // one of the half-edges emantating from the vertex
    
    };
	
	struct HE_face {
        HE_edge* edge;  // one of the half-edges bordering the face
    };
	
	遍历:
    HE_vert* vert1 = edge->vert;
    HE_vert* vert2 = edge->pair->vert;

    HE_face* face1 = edge->face;
    HE_face* face2 = edge->pair->face;
 
 
    HE_edge* edge = face->edge;
    do {
       // do something with edge
       edge = edge->next;
     
    } while (edge != face->edge);
 
 
    HE_edge* edge = vert->edge;

    do {
        // do something with edge, edge->pair or edge->face
        edge = edge->pair->next;
    } while (edge != vert->edge);
 

在OFF的读取中,需要把OFF的格式转化为半边数据结构,我是这样做的:
先读入文件,结构体就用上面那些,然后读入点就正常存一个点
读入面的时候比如:4 0 1 2 3,那就4条边,分别是0->1, 1->2, 2->3, 3->0。
然后这些边分别是一个HE_edge对象。
然后面的话,每一行都是一个HE_face对象。
每读入一个边都进行一个他们相互之间的联结,除了pair不能直接赋值,其他的都可以。
然后处理边的pair,这里是使用map,map的类型是 pair<>, *edge(这里的pair<>是数据类型)
每次加边的时候都加一个map,然后搜一下map中有无相反的边,有的话互相pair属性联结一下。
然后就,完成啦。

对于,至于绘图工作,画的是线图,在读入边的时候,GL_LINE_LOOP画一下就好啦。

然后这里还有一个其他功能:bianli(),这个函数是实现了把0这个点变成绿色,相连的边变成蓝色,相邻的点变成红色。

代码:
lab6.cpp

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <GL/glut.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <map>
#include "ArcBall.h"
using namespace std;

struct HE_vert;
struct HE_face;
struct HE_edge;

struct HE_vert {
    float x;
    float y;
    float z;
    HE_edge* edge;  // one of the half-edges emantating from the vertex
};

struct HE_face {
    HE_edge* edge;  // one of the half-edges bordering the face
};

struct HE_edge {
    int id;
    HE_vert* vert;   // vertex at the end of the half-edge
    HE_edge* pair;   // oppositely oriented adjacent half-edge 
    HE_face* face;   // face the half-edge borders
    HE_edge* next;   // next half-edge around the face
};

class HE_off {
private:
    int vert_cnts, face_cnts, edge_cnts;
    map<pair<int, int>, HE_edge*> edge_map;
    HE_vert* HE_verts;
    HE_face* HE_faces;
    HE_edge* HE_edges;
public:
    HE_off() {}
    ~HE_off() {
        delete HE_verts;
        delete HE_faces;
        delete HE_edges;
    }


    void read_off() {
        char theOff[233] = "bumpy.off";
        // cin >> theOff;
        ifstream fin(theOff);
        if (!fin.is_open()) {
            puts("Error opening file.");
            exit(1);
        }
        string isOff;
        do {
            fin >> isOff;
        } while (isOff[0] == '#');
        if (isOff != "OFF") {
            puts("This is not a .off file.");
            exit(1);
        }

        fin >> this->vert_cnts >> this->face_cnts >> this->edge_cnts;

        this->HE_verts = new HE_vert[this->vert_cnts];

        //glBegin(GL_POINTS);

        for (int i = 0; i < vert_cnts; i++) {
            float a, b, c;
            fin >> a >> b >> c;
            (this->HE_verts + i)->x = a, (this->HE_verts + i)->y = b, (this->HE_verts + i)->z = c;
            //cout << a << b << c << endl;
            //glVertex3d(a, b, c);
        }
        //glEnd();


        this->HE_faces = new HE_face[this->face_cnts];
        this->HE_edges = new HE_edge[this->face_cnts*5];

        for (int i = 0; i < face_cnts; i++) {
            int n;
            int k[10];
            fin >> n;

            //cout << "face_point: ";
            for (int j = 0; j < n; j++) {
                fin >> k[j];
            }

            //glBegin(GL_POLYGON);
            glBegin(GL_LINE_LOOP);
            for (int j = 0; j < n; j++) {
                int t = (j + 1) % n;

                (this->HE_edges + i * n + j)->face = (this->HE_faces + i);
                (this->HE_edges + i * n + j)->vert = (this->HE_verts + k[t]);
                (this->HE_edges + i * n + j)->next = (this->HE_edges + i * n + t);
                (this->HE_edges + i * n + j)->id = i * n + j;

                this->edge_map[make_pair(k[j], k[t])] = (this->HE_edges + i * n + j);

                auto iter = edge_map.find(make_pair(k[t], k[j]));
                if (iter != edge_map.end()) {
                    (this->HE_edges + i * n + j)->pair = iter->second;
                    iter->second->pair = (this->HE_edges + i * n + j);
                }
                 
                (this->HE_faces + i)->edge = (this->HE_edges + i * n + j);

                // cout << "j: " << j << ", i*n+j:" << i*n+j << " k[j]:" << k[j] << ",k[t]:" << k[t] << endl;
                (this->HE_verts + k[j])->edge = (this->HE_edges + i * n + j);

                float a, b, c;
                a = (this->HE_verts + k[j])->x;
                b = (this->HE_verts + k[j])->y;
                c = (this->HE_verts + k[j])->z;

                //glBegin(GL_POINT);
                glVertex3f(a, b, c);
                //cout << k << " ";
            }
            glEnd();
            //cout << endl;
        }
    }

    void bianli() {
        float a, b, c;
        a = (this->HE_verts)->x;
        b = (this->HE_verts)->y;
        c = (this->HE_verts)->z;

        //设置点的大小
        glPointSize(7);
        //进行平滑处理 
        glEnable(GL_POINT_SMOOTH);
        glHint(GL_POINT_SMOOTH, GL_NICEST);

        glBegin(GL_POINTS);
        glColor3f(0, 255, 0);
        glVertex3f(a, b, c);
        // cout << "green:" << a << ", " << b << ", " << c << endl;
        glEnd();

        HE_edge* edge = (this->HE_verts)->edge;

        do {
            // do something with edge, edge->pair or edge->face
            // cout << "id: " << edge->id << "," << edge->vert->x << "," << edge->vert->y << "," << edge->vert->z << endl;
            glBegin(GL_POINTS);
            glColor3f(255, 0, 0);
            glVertex3f(edge->vert->x, edge->vert->y, edge->vert->z);
            // cout << "red:" << edge->vert->x << ", " << edge->vert->y << ", " << edge->vert->z << endl;
            glEnd();

            glBegin(GL_LINE_LOOP);
            //glLineWidth(3.0f);
            glColor4ub(0, 0, 255, 255);
            glColor3f(0, 0, 255);
            glVertex3f(a, b, c);
            glVertex3f(edge->vert->x, edge->vert->y, edge->vert->z);
            // cout << "blue:" << edge->vert->x << ", " << edge->vert->y << ", " << edge->vert->z << endl;
            glEnd();

            edge = edge->pair->next;
        } while (edge != (this->HE_verts)->edge);

    }
};



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(ArcBall->rightPan, ArcBall->upPan, 0);
    glScalef(ArcBall->zoomRate, ArcBall->zoomRate, ArcBall->zoomRate);//2. 缩放
    glMultMatrixf(ArcBall->Transform.M);                        //3. 旋转
    //glutWireCube(1.0);

    /*glBegin(GL_POLYGON);*/


    HE_off myoff;
    myoff.read_off();
    myoff.bianli();

    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;
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
        ArcBall->isRClicked = false;
    else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
        ArcBall->isMClicked = true;
        move(x, y);
    }
    else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP)
        ArcBall->isMClicked = false;
    ArcBall->upstate();
    glutPostRedisplay();


}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(640, 480);
    //glutCreateWindow("TEST_Arcball");
    glutCreateWindow("MY_OFF");

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

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

    glutMainLoop();

    return 0;
}

arcball.h

//
// Created by pacer on 2019/6/19.
//

#ifndef RORATION_ARCBALL_H
#define RORATION_ARCBALL_H

#endif //RORATION_ARCBALL_H

///ArcBall.h///


#include <stdlib.h>

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

#include <GL/glut.h>
#include "math.h"

//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;
    float lastUp;
    float upPan;
    float lastRight;
    float rightPan;

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

} ArcBallT;

arcball.cpp

//
// Created by pacer on 2019/6/19.
//


///ArcBall.cpp

//#include <windows.h>
#include <GL/glut.h>
#include <iostream>

#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;
    }
    else if (!this->isMoving && this->isMClicked) {                    // 开始移动
        this->isMoving = true;                                        // 设置移动为变量为true
        this->LastPt = this->MousePt;
        this->lastUp = this->upPan;
        this->lastRight = this->rightPan;
    }
    else if (this->isMoving) {                  //正在拖动
        if (this->isMClicked) {                   //正在点着中键
            std::cout << "Mid CCCCCCCCCCCCCCCCCCCCCCCCCCCC******************\n";
            Point2fSub(&this->MousePt, &this->LastPt);
            this->rightPan = this->lastRight + this->MousePt.s.X * this->AdjustWidth * 2;
            this->upPan = this->lastUp - this->MousePt.s.Y * this->AdjustWidth * 2;
        }
        else {        //松开了
            this->isMoving = false;
        }
    }
}
/*
void ArcBall_t::mousemove(WPARAM wParam,LPARAM lParam)
{
this->MousePt.s.X = (GLfloat)LOWORD(lParam);
this->MousePt.s.Y = (GLfloat)HIWORD(lParam);
this->isClicked   = (LOWORD(wParam) & MK_LBUTTON) ? true : false;
this->isRClicked  = (LOWORD(wParam) & MK_RBUTTON) ? true : 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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值