OpenGL glut OFF 读取 + 半边数据结构存储
文件格式:
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-edgeHE_edge* pair; // oppositely oriented adjacent half-edge HE_face* face; // face the half-edge bordersHE_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 edgeedge = edge->next;} while (edge != face->edge);HE_edge* edge = vert->edge;do {// do something with edge, edge->pair or edge->faceedge = 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-edgeHE_edge* pair; // oppositely oriented adjacent half-edge HE_face* face; // face the half-edge bordersHE_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);ballArcBall->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 eventglutMainLoop();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 majorunion { 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 majorunion { 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://把二维点映射到三维点inlinevoid _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;public://构造/析构函数ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);~ArcBall_t() { };//设置边界inlinevoid 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.0fvoid 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坐标为0NewVec->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; // 设置拖动为变量为truethis->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; // 设置拖动为变量为truethis->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 // 如果放开鼠标,设置拖动为falsethis->isDragging = false;}else if (!this->isMoving && this->isMClicked) { // 开始移动this->isMoving = true; // 设置移动为变量为truethis->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);//如果不为0if (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;}}
}
OpenGL glut OFF 读取 + 半边数据结构存储相关推荐
- 三维形体的数据结构(1)半边数据结构
这其实是我学习图形学以来第一次真正接触数据结构的一篇博客,除了之前用markdown写的那篇文章,那个就是入个小门. 为什么我开始接触数据机构,因为在我做第一次细分的时候就遇到了麻烦,比如DOO-SA ...
- DOO-SABIN 细分正方体(2)利用半边数据结构表示(一次和两次细分)
之前做过一次细分,可是效果相当不好.也不是效果不好,就是效率特别低,之后我自学了半边数据结构,这篇博文就要对半边数据结构表示的正方体进行细分,希望可以在这篇博文搞定之后就可以实现对任意的立方体进行细分 ...
- 基于C++和OpenGL (GLUT) 实现太阳系行星系统
基于C++和OpenGL (GLUT) 实现太阳系行星系统 效果图: 分析与设计 OpenGL 包含了很多渲染函数,但是他们的设计目的是独立于任何窗口系统或操作系统的.因此,它自身并没有包含创建打开窗 ...
- CC2541之发现服务、特征值及读取特征值中存储值的详细过程
一.通过SimpleBLECentral工程分析CC2541作为主机时是如何发现从机的服务和特征值的,以及读取特征值的具体过程 二.服务和特征值 1.一个工程可以有多个服务,比如按键服务.心率计服务. ...
- 半边数据结构【Half Edge】
表示多边形网格的常用方法是共享顶点列表和存储其顶点索引的面列表.这种表示既方便又对于许多目的都是有效的,但是在某些领域它被证明是无效的.Half Edge就是解决网格中邻接元素查询的一种数据结构. 1 ...
- OpenGL(glut)模拟太阳系:太阳,地球,月球,火星
GitHub项目地址OpenGL(glut)模拟太阳系:太阳,地球,月球,火星 核心代码如下: // orgin.cpp : 此文件包含 "main" 函数.程序执行将在此处开始并 ...
- Ubuntu下安装OpenGL/Glut库
http://www.libaqiang.com/?p=78330 1.Ubuntu下安装OpenGL/Glut库 OpenGL(全写Open Graphics Library)是个定义了一个跨编程语 ...
- android逐行写入读取_Android外部存储-读取,写入,保存文件
android逐行写入读取 Android external storage can be used to write and save data, read configuration files ...
- 使用单链表数据结构存储结构化的学生信息
使用单链表数据结构存储结构化的学生信息 一.题目描述 定义一个学生结构体,包含有:学号,姓名,成绩.输入N个学生的信息,并进行基本的链表操作.(更好的阅读体验,请在我的博客网站上阅读此文:使用单链表数 ...
最新文章
- 南方人物周刊:智能手机割据战
- 04-树7 二叉搜索树的操作集(c语言实现)
- SAP Spartacus 的基于outlet 的页面扩展
- 【java】详解java多线程
- 《java入门第一季》之类面试题
- osg+ActiveQT嵌入ie64位
- ubuntu 安装 sublime
- Spring Boot
- python去除视频马赛克_十行python代码教你如何去除万恶的,如s一样的马赛克
- 【设计鉴赏】张艺谋《影》震撼人心的海报设计
- griddata三维空间插值
- linux查看其他用户计划任务,Linux计划任务(crond、atd)
- PS常用案例步骤详解,自学 Photoshop 2022 Mac版,多个PS后期修图小案例笔记
- 蓉叶云库——简单介绍seo技术
- thread ‘main‘ panicked at ‘called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound
- Ruff 公开课回顾——物联网应用已经落地,区块链技术紧随其后
- 杨振宁六大数理工作赏析 | 祝贺杨先生百岁华诞
- C语言中extern的作用
- 以下 D 不是MYSQL的对象权限_数据库课后习题及答案
- 如何扫描图片变成文字?手把手教你转换操作
热门文章
- [SWPUCTF 2021 新生赛]
- 视频编解码 — 码控算法
- Zcash halo2 背后技术衍化介绍
- 删除磁盘上的表空间后再删除数据库中的表空间——ORA-01549:表空间非空,请使用including contents选项
- 计算机病毒程序没有文件名 是靠 识别的,计算机理论选择问题和答案.doc
- 前后端数据加解密的几种方式比较
- 计算机组成原理数据流通图作用,计算机组成原理-第14-15讲(第5章).ppt
- 深入浅出地理解机器人手眼标定
- .ren助力高校BBS圈,sdada.ren为山工艺学子服务~
- 什么软件运用计算机处理图像,平面设计中计算机图形图像处理软件的运用探究...